Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

legolagents-0.1.0.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

legolagents-0.1.0-py3-none-any.whl (104.9 kB view details)

Uploaded Python 3

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

Hashes for legolagents-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fd9b453f214398d9ce82fa319579dd93932ec61a4d0ee9157ad2da68c0564fa5
MD5 04cfe8cd77d6950d94e00e2454f3ef76
BLAKE2b-256 4f27a08d951e13dfce3908a9a2cbb02a538ee058ae888715f02474b7a2bf9ff8

See more details on using hashes here.

Provenance

The following attestation bundles were made for legolagents-0.1.0.tar.gz:

Publisher: publish.yml on smartlawyer-ai/legolagents

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for legolagents-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cfb2f45571ccfed07615ac9331ab43f49ea0fba7d5303bf097ead813a7dfa410
MD5 d1dc2f00cc2c2dcf2ad309938c1cee58
BLAKE2b-256 0dcc818664b7d27464abea9888d3a7269bc485841e91c7981eaf6ab39eb78ccb

See more details on using hashes here.

Provenance

The following attestation bundles were made for legolagents-0.1.0-py3-none-any.whl:

Publisher: publish.yml on smartlawyer-ai/legolagents

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page