Legal AI agents framework — extension of smolagents with structured, jurisdiction-agnostic legal reasoning (French law example included)
Project description
legolagents turns any legal corpus — case law, statutes, your own database — into an agent that reasons like a jurist: it checks whether a decision is still valid before citing it, walks the citation lineage, detects reversals, and revises contracts with native Word tracked changes. Jurisdiction-agnostic by default — set jurisdiction="France" ("Belgium"…) to ground it in a given legal system, or leave it generic and plug in your own multi-jurisdiction corpus.
pip install legolagents
What actually changes
Without legolagents, a smolagents agent answers a legal question by keyword search. It might cite a decision that was overturned three years ago without knowing it.
With legolagents, the agent automatically applies a jurist's protocol: it checks the validity of each decision, distinguishes landmark decisions from case-specific ones, walks citations across several levels, and flags divergences between courts or jurisdictions.
Quickstart (any jurisdiction)
A legal agent works on a corpus — a body of law (e.g. "GDPR", "French Labor Code", "Delaware corporate law"). Plug yours in by implementing four methods — get_law, search_law, get_jp, search_jp — and the agent's tools are built for you, no Tool subclass to write:
from legolagents import LegalResearchAgent, LegalCorpus, LegalSource, SourceType, Authority
from smolagents import LiteLLMModel
class MyCorpus(LegalCorpus):
name = "GDPR"
jurisdiction = "EU"
def get_law(self, ref):
payload = my_database.fetch_article(ref)
return LegalSource.from_payload(payload, kind=SourceType.REGULATION, authority=Authority.BINDING)
def search_law(self, query, limit=5):
return LegalSource.from_payloads(my_database.search_articles(query, limit),
kind=SourceType.REGULATION, authority=Authority.BINDING)
def get_jp(self, ref): ... # same idea, kind=SourceType.CASE_LAW
def search_jp(self, query, limit=5): ...
model = LiteLLMModel(model_id="anthropic/claude-sonnet-4-5")
agent = LegalResearchAgent(corpus=MyCorpus(), model=model) # jurisdiction/legal_domain default from the corpus
print(agent.run("What are a processor's obligations under Article 28 GDPR, and how have courts interpreted them?"))
That's the whole integration surface. The agent automatically checks the validity of decisions, walks the citation graph, and answers with a certainty level: ✅ Established law, ⚡ Trending, ⚠️ Isolated, or ❌ Superseded.
Don't have a case law database yet? See the Example: bootstrapping on the French market section below — a ready-to-use LegalCorpus to try the framework without building anything.
Under the hood: the ontology, and adding your own tools
Every LegalSource your corpus returns (from get_law, search_jp, etc.) is built on one universal shape: SourceType × Authority. Every legal system on earth mixes codified sources (statutes, regulations, treaties) and case law — what actually changes from one jurisdiction to the next is authority, not type. A court decision is PERSUASIVE in a civil law country, BINDING in a common law one — same SourceType.CASE_LAW either way:
from legolagents import SourceType, Authority, LegalSource
statute = LegalSource(ref="L1235-3", kind=SourceType.STATUTE, authority=Authority.BINDING)
case = LegalSource.from_payload(
{"number": "21-14.027", "cited_by_count": 42, "importance_score": 90},
kind=SourceType.CASE_LAW, authority=Authority.PERSUASIVE,
)
case.relates_to(statute, how="interprets")
print(case.to_markdown())
# **[case_law] 21-14.027** (💬 persuasive) ✅ Established law
# ↳ interprets L1235-3
You don't build these one at a time in application code — from_payload()/from_payloads() map your data source's raw records in bulk (that's what a real get_law/search_jp implementation does), and authority/certainty/relations come from your data's own metadata (binding vs. persuasive, cited_by_count, superseded_by…), not a separate step you run afterward.
The four corpus methods are the minimum, not the ceiling. Need a capability that doesn't fit get_law/search_law/get_jp/search_jp — say, "what cites this article"? Add a plain function with smolagents' @tool decorator: the docstring becomes the tool's description, the Args: block becomes its input schema — that's what the agent actually sees.
from smolagents import tool
from legolagents import LegalSource, SourceType, Authority
@tool
def articles_cited_by(ref: str) -> str:
"""
List every decision that cites, interprets, or applies a given statute article.
Args:
ref: Reference of the article to look up (e.g. "L1235-3").
"""
hits = my_database.find_citing(ref)
sources = LegalSource.from_payloads(hits, kind=SourceType.CASE_LAW, authority=Authority.PERSUASIVE)
return "\n".join(f"- {s.to_markdown()}" for s in sources)
agent = LegalResearchAgent(corpus=MyCorpus(), tools=[articles_cited_by], model=model)
tools= and corpus= combine freely — the agent gets the four standard tools plus whatever you add. See legolagents.ontology for the full model (source types, authority levels, and the relation types — cites, interprets, applies, distinguishes, overturns, supersedes, implements).
Playbooks — a workflow in one line
from legolagents.playbooks import Playbook
Playbook.quick("NDA Review", points=[
"Parties — who are the contracting parties?",
"Term — how long does the confidentiality obligation last?",
"Carve-outs — what information is excluded from confidentiality?",
]).register()
Playbook.quick(...).register() builds and registers a structured analysis workflow in one call — points accept plain "Label — description" strings, id and document type are inferred from the title. Then hand it to any document agent:
from legolagents import LegalDocumentAgent
from legolagents.playbooks import PlaybookLibrary
agent = LegalDocumentAgent(model=model)
playbook = PlaybookLibrary.get("nda_review")
agent.run(f"Document: my_nda.docx\n\n{playbook.to_prompt()}")
For full control (flag conditions, custom output format, extra instructions), Playbook and PlaybookPoint remain available directly — see the built-in French-law playbooks below for an example.
Other examples
Contract revision with Accept / Reject in Word
from legolagents import LegalDocumentAgent
agent = LegalDocumentAgent(model=model, jurisdiction="France", legal_domain="employment law")
agent.review(
"contract.docx",
"The non-compete clause has no financial consideration — fix it",
output_path="contract_revised.docx",
)
# → open in Word or LibreOffice → Accept / Reject each change
No full document regeneration. The agent surgically edits the relevant clauses and injects native Word tracked-change tags (<w:del> / <w:ins>).
Structured analysis of a commercial lease (French law example)
from legolagents import LegalDocumentAgent
from legolagents.playbooks import PlaybookLibrary
agent = LegalDocumentAgent(model=model, jurisdiction="France")
playbook = PlaybookLibrary.get("bail_commercial") # 14 points, French Commercial Code L145
agent.run(f"Document: lease.docx\n\n{playbook.to_prompt(output_path='analysis.docx')}")
# → Word report: termination clause without formal notice ⚠️, unlawful property tax pass-through ⚠️…
Comparing N documents across M criteria
agent.compare(
["lease_A.docx", "lease_B.docx", "lease_C.docx"],
criteria=["Term", "Indexation", "Termination clause", "Tenant charges"],
output_path="due_diligence.docx",
)
# → matrix with automatic flagging of risky clauses
Plug in your own database
LegalCorpus doesn't care what's behind it — Qdrant, Elasticsearch, a REST API, a SQL database, or any legal MCP server. Implement the four methods against your backend and return LegalSource objects (built in bulk with from_payload/from_payloads, see above).
If you'd rather not implement a corpus at all, tools=[...] still accepts any smolagents Tool list directly — corpus= and tools= can also be combined (e.g. a corpus for research plus extra document tools).
Example: bootstrapping on the French market (SmartLawyer MCP)
Don't have a case law database yet? SmartLawyer MCP gives access to 1M+ French court decisions and 13 Legal Graph tools — handy for prototyping a legolagents project without building anything. Free developer tier.
pip install 'legolagents[mcp]'
from legolagents import LegalResearchAgent
from legolagents.mcp import SmartLawyerCorpus
with SmartLawyerCorpus(api_key="sk-sl-your-key") as corpus: # jurisdiction="France" by default
agent = LegalResearchAgent(corpus=corpus, model=model)
agent.run("Is decision 17-19.860 still valid?")
SmartLawyerCorpus implements LegalCorpus on top of SmartLawyer's MCP tools, and also exposes its graph/reversal-detection tools (find_revirements, superseded_chain, get_legal_graph…) alongside the standard four. Prefer the lower-level SmartLawyerMCP (raw MCP tool list, tools= instead of corpus=) if you want the tools unmapped to LegalSource.
→ Get a free API key · MCP documentation
This connector is one example among other possible legal MCP servers (see "Plug in your own database" above) — the core of the framework doesn't depend on it.
Want a full chat UI instead of a script? examples/06_chainlit_smartlawyer_chatbot.py wires the same agent into a working Chainlit chatbot in about 15 lines.
Available playbooks (18, across 5 jurisdictions)
Playbooks are organized by jurisdiction, not language — French is spoken in France, Belgium, Switzerland, Québec… each with its own law, so grouping by legal system (playbooks/library/fr/, us/, uk/, de/, eu/) keeps a playbook's content coherent. Filter or list them with PlaybookLibrary.list(jurisdiction="us") / PlaybookLibrary.jurisdictions().
France (fr) — French Commercial/Labor/Civil Code:
| ID | Document | Analysis points |
|---|---|---|
bail_commercial |
Commercial lease | 14 (French Commercial Code L145-1) |
contrat_travail |
Employment contract (CDI/CDD) | 12 (French Labor Code) |
pacte_associes |
Shareholders' agreement | 15 |
convention_credit |
Credit agreement | 18 |
United States (us) — federal law plus Delaware/California/New York variance:
| ID | Document | Analysis points |
|---|---|---|
us_nda |
NDA (mutual or one-way) | 13 (DTSA, state noncompete variance) |
us_employment_agreement |
Employment agreement (at-will) | 12 (FLSA, state noncompete variance) |
us_commercial_lease |
Commercial lease | 13 (state landlord-tenant variance) |
us_saas_msa |
SaaS agreement / MSA | 13 (UCC, state privacy law, AI-training clauses) |
United Kingdom (uk) — England & Wales law:
| ID | Document | Analysis points |
|---|---|---|
uk_nda |
NDA / confidentiality agreement | 12 (Coco v Clark, Trade Secrets Regs 2018) |
uk_employment_contract |
Employment contract | 13 (Employment Rights Act 1996/2025) |
uk_commercial_lease |
Commercial lease | 13 (Landlord and Tenant Act 1954 Part II) |
uk_saas_msa |
SaaS agreement / MSA | 13 (UCTA 1977, UK GDPR) |
Germany (de) — Bundesrepublik Deutschland, content in German:
| ID | Document | Analysis points |
|---|---|---|
de_geheimhaltungsvereinbarung |
NDA | 12 (GeschGehG, § 307 BGB) |
de_arbeitsvertrag |
Employment contract | 13 (§ 622 BGB, § 74 HGB, KSchG) |
de_gewerbemietvertrag |
Commercial lease | 13 (§ 550 BGB Schriftform) |
EU (eu) — supranational, cross-border regulatory content:
| ID | Document | Analysis points |
|---|---|---|
eu_data_processing_agreement |
Data Processing Agreement | 13 (GDPR Art. 28) |
eu_gdpr_compliance_review |
GDPR compliance review | 14 (GDPR + EU AI Act overlap) |
eu_distribution_agreement |
Distribution / vertical agreement | 13 (VBER 2022/720) |
These playbooks ship ready-to-use; write your own with Playbook.quick(...) (see above) for any other jurisdiction or document type. Legal citations reflect law as researched at authoring time — always verify current status before relying on them for real matters.
Contributing
Issues and PRs welcome — additional playbooks, new tool interfaces, support for other jurisdictions (Belgium, Switzerland, Quebec, common law…).
License
Apache 2.0 · Built by SmartLawyer AI
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file legolagents-0.1.0.tar.gz.
File metadata
- Download URL: legolagents-0.1.0.tar.gz
- Upload date:
- Size: 1.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd9b453f214398d9ce82fa319579dd93932ec61a4d0ee9157ad2da68c0564fa5
|
|
| MD5 |
04cfe8cd77d6950d94e00e2454f3ef76
|
|
| BLAKE2b-256 |
4f27a08d951e13dfce3908a9a2cbb02a538ee058ae888715f02474b7a2bf9ff8
|
Provenance
The following attestation bundles were made for legolagents-0.1.0.tar.gz:
Publisher:
publish.yml on smartlawyer-ai/legolagents
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
legolagents-0.1.0.tar.gz -
Subject digest:
fd9b453f214398d9ce82fa319579dd93932ec61a4d0ee9157ad2da68c0564fa5 - Sigstore transparency entry: 2297688701
- Sigstore integration time:
-
Permalink:
smartlawyer-ai/legolagents@76f6bede63e9180a3fb2451f3ea4e79cd1294b79 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/smartlawyer-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@76f6bede63e9180a3fb2451f3ea4e79cd1294b79 -
Trigger Event:
push
-
Statement type:
File details
Details for the file legolagents-0.1.0-py3-none-any.whl.
File metadata
- Download URL: legolagents-0.1.0-py3-none-any.whl
- Upload date:
- Size: 104.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cfb2f45571ccfed07615ac9331ab43f49ea0fba7d5303bf097ead813a7dfa410
|
|
| MD5 |
d1dc2f00cc2c2dcf2ad309938c1cee58
|
|
| BLAKE2b-256 |
0dcc818664b7d27464abea9888d3a7269bc485841e91c7981eaf6ab39eb78ccb
|
Provenance
The following attestation bundles were made for legolagents-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on smartlawyer-ai/legolagents
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
legolagents-0.1.0-py3-none-any.whl -
Subject digest:
cfb2f45571ccfed07615ac9331ab43f49ea0fba7d5303bf097ead813a7dfa410 - Sigstore transparency entry: 2297688867
- Sigstore integration time:
-
Permalink:
smartlawyer-ai/legolagents@76f6bede63e9180a3fb2451f3ea4e79cd1294b79 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/smartlawyer-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@76f6bede63e9180a3fb2451f3ea4e79cd1294b79 -
Trigger Event:
push
-
Statement type: