Skip to content

Repository files navigation

LangGraph OKF Consumer (Legal Knowledge Graph)

A demonstration consumer for Google's Open Knowledge Format (OKF v0.2), using LangGraph for LLM-guided graph traversal over fictional legal contracts, with an offline keyword fallback.

This is a partial implementation, not a conformance-certified consumer. The bundled agreements and human review records are fictional fixtures. See bundle scope for missing evidence and calculation limits.

Scope Note: This repository focuses exclusively on the OKF Consumer setup. Ingestion/producer logic will be addressed in a separate project.


Why OKF Over Conventional RAG for Legal Documents

Conventional RAG chops legal documents into isolated vector chunks, losing:

  1. Contract Structure: Agreements, sections, clauses, and exhibits are flattened.
  2. Cross-References: Clauses referencing definitions (e.g. "Confidential Information", "Fees") or addenda (e.g. DPA supercaps) are severed.
  3. Trust & Provenance: Cannot distinguish attorney-reviewed clauses from AI drafts.
  4. Freshness: Outdated or superseded terms pollute similarity search.

OKF (Open Knowledge Format v0.2) represents legal knowledge as a directory tree of Markdown files with YAML frontmatter:

  • Progressive Disclosure: Agents navigate using index.md files at each level, loading only what is needed.
  • Trust Tiers: human-reviewed, machine-confirmed, and unverified are inferred from frontmatter actor signals.
  • Relational Links: Standard Markdown links ([Fees](/definitions/fees.md)) create explicit, traversable graph edges.
  • Attested Computations: Deterministic formulas (e.g., liability caps, cure periods) are evaluated mathematically rather than guessed.

Architecture

flowchart TD
    Plan[Plan: LLM selects sections] --> Navigate[Navigate: LLM selects concepts]
    Navigate --> Inspect[Inspect: load evidence and check trust]
    Inspect --> Review[Review: LLM selects more linked evidence]
    Review -->|More evidence, within depth limit| Inspect
    Review -->|Enough evidence or limit reached| Compute[Compute: registered Python rules]
    Compute --> Synthesize[Synthesize: LLM writes cited answer]
Loading

Without an LLM, selection and link expansion use deterministic fallbacks and synthesis produces an evidence report. The review step runs inside expand.py.

langgraph-okf/
├── bundles/
│   └── legal_sample/                 # Fictional OKF demonstration bundle
│       ├── index.md                  # Root progressive disclosure index
│       ├── log.md                    # Bundle update history (§3.1 & §9)
│       ├── definitions/              # Legal definition concepts
│       ├── contracts/                # Agreements & Addenda
│       │   ├── msa/                  # Master Services Agreement & Clauses
│       │   ├── dpa/                  # Data Processing Addendum (2x Supercap)
│       │   └── sla/                  # Service Level Agreement
│       └── computations/             # Attested Computations (Liability, Notice)
├── src/
│   └── langgraph_okf/                # OKF v0.2 Consumer Core
│       │── models.py             # Pydantic models for Concept, Frontmatter, TrustTier
│       │── parser.py             # Permissive YAML+Markdown parser (§4 & §11)
│       │── bundle.py             # Bundle reader, index traversal, link resolution
│       │── trust.py              # Trust tier evaluator & freshness checker
│       ├── agent/                    # LangGraph Workflow Layer
│       │   ├── state.py              # LegalDiscoveryState schema
│       │   ├── context.py            # Per-run bundle, LLM, and policy dependencies
│       │   ├── reasoning.py          # Validated LLM selections and usage accounting
│       │   ├── llm.py                # OpenRouter ChatOpenAI factory with custom headers
│       │   ├── tools.py              # Attested computation execution tools
│       │   ├── nodes/                # Individual Node Files
│       │   │   ├── plan.py           # Planning & root index evaluation
│       │   │   ├── navigate.py       # Progressive disclosure index traversal
│       │   │   ├── inspect.py        # Concept inspection & trust evaluation
│       │   │   ├── expand.py         # Relational link graph expansion
│       │   │   ├── compute.py        # Deterministic Attested Computation execution
│       │   │   └── synthesize.py     # Grounded legal synthesis with citations
│       │   └── graph.py              # Compiled LangGraph workflow
│       ├── cli.py                    # Interactive query & inspection CLI
│       └── settings.py               # OpenRouter & OKF configuration settings
└── tests/
    ├── test_okf_parser.py            # Permissive parsing conformance tests
    ├── test_trust_evaluator.py       # Trust signal & lifecycle verification tests
    ├── test_bundle_traversal.py      # Progressive disclosure & link resolution tests
    ├── test_agent_workflow.py        # End-to-end LangGraph agent discovery tests
    ├── test_agent_reasoning.py       # Semantic selection and bounded evidence review
    ├── test_runtime_context.py       # Per-run dependency and policy isolation
    ├── test_usage_metrics.py         # Token, cost, timing, and fallback reporting
    └── test_audit_regressions.py     # Security and consumer behavior regressions

Setup & Quickstart

Prerequisites

  • Python >= 3.14
  • uv

Installation

git clone https://github.com/ConceptCodes/langgraph-okf.git
cd langgraph-okf
uv sync

Configuration

Create a .env file (optional, defaults to deterministic fallback if no API key is provided):

OPENROUTER_API_KEY=your_openrouter_api_key_here
OPENROUTER_MODEL=google/gemini-3.8-flash

Running the CLI

Queries end with a Run Metrics table showing total time (setup and graph execution), LLM time, the returned model name, input/output/total tokens, and request cost in USD. Cost uses OpenRouter usage accounting, not a hard-coded price estimate. Unreported usage or failed calls show unavailable values; offline runs show zero tokens and cost. Metrics aggregate all planning, navigation, evidence-review, and synthesis calls, with a per-call breakdown. They do not cover account-wide usage or separately billed SDK retry attempts. If any call lacks usage, the corresponding aggregate is unavailable rather than undercounted.

1. Run a Legal Discovery Query

uv run langgraph-okf query 'What is the liability cap under the MSA, what exceptions apply, and how does a data breach affect it with $100,000 in fees?'

2. Inspect a Concept Document

uv run langgraph-okf inspect contracts/msa/clauses/limitation_of_liability

3. List All Concepts in the Legal Bundle

uv run langgraph-okf list

4. Test Semantic Retrieval or Offline Mode

uv run langgraph-okf query 'What remedies are available if the platform goes dark?'
OPENROUTER_API_KEY='' uv run langgraph-okf query 'What notice is required for termination?'

The final answer appears in the Grounded Evidence & Synthesis panel, followed by Run Metrics and, for live runs, LLM Calls. The traversal log records model selections and fallbacks. Keep dollar amounts inside single quotes to prevent shell expansion.


Running Tests

uv run pytest -v
uv run ruff check src tests

Tests force offline mode and use the sample bundle, regardless of local .env credentials.

Consumer behavior and limits

With an LLM configured, planning selects sections from directory indexes and navigation selects concepts from index titles/descriptions. After inspection, the LLM reviews retrieved evidence and can request more offered linked concepts or stop. Each selection is checked against the candidate IDs; arbitrary paths are rejected. Malformed or failed selection calls use deterministic traversal as a fallback. Empty planning/navigation selections also fall back; an empty review selection stops expansion. Trust checks and registered Python calculations remain deterministic.

There are at most MAX_TRAVERSAL_DEPTH + 3 application-level LLM calls: planning, navigation, one review per expansion round, and synthesis. Phases without candidates are skipped. SDK retries may add network requests. Offline mode uses no LLM calls.

The graph uses LangGraph runtime context. Every node accepts Runtime[Context]. Each invocation supplies one bundle instance, an optional chat model (None means offline), and fixed trust/traversal policy. Nodes do not read global settings. Query progress and results remain in graph state.

from langgraph_okf.agent import Context, build_legal_discovery_graph
from langgraph_okf.bundle import OKFBundle

graph = build_legal_discovery_graph()
context = Context(bundle=OKFBundle("bundles/legal_sample"), max_traversal_depth=3)
result = graph.invoke(
    {"query": "What is the standard liability cap with $100,000 in fees?"},
    context=context,
    config=context.invocation_config,
)

The CLI constructs Context.from_settings(settings) once per query. Python callers must now pass context explicitly; get_openrouter_llm also requires an explicit Settings argument. Supply config=context.invocation_config so LangGraph's step limit accommodates the selected traversal depth. One compiled graph can be reused with different contexts, including concurrent calls.

  • Paths and symlinks must remain inside the bundle. Index navigation follows nested directories; relational expansion uses MAX_TRAVERSAL_DEPTH as a link-hop limit.
  • MIN_TRUST_TIER selects evidence for this application's workflow. STRICT_VALIDATION=true additionally excludes stale/deprecated concepts. The underlying parser remains permissive; these settings are application policy, not OKF validity checks.
  • Verification mappings and lists are supported. Trust is inferred from declared actors; identities and signatures are not authenticated.
  • Only two registered sample computations run. They require explicit inputs and reject unknown executors and invalid numeric values. Query classification is heuristic, with assumptions shown in the output. Arbitrary bundle code is never executed.
  • Calculation outputs are local results, not independently attested receipts.
  • Offline output includes the retrieved text and citations; it is an evidence report, not a substitute for legal interpretation. Configuring an API key enables sending the query, index metadata, and retrieved evidence to OpenRouter for selection, evidence review, and synthesis.
  • The parser supports inline Markdown links, not the full CommonMark link grammar. Legacy v0.1 provenance conversion and external computation runtimes are not implemented.
  • Run CLI examples from the repository root, or set BUNDLE_PATH to an absolute directory. The sample bundle is not installed as package data.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages