Skip to main content

OpenTerms protocol integration for LangChain: permission-aware AI agents

Project description

langchain-openterms

Permission-aware AI agents for LangChain. Checks a domain's openterms.json before your agent acts, so it knows what it's allowed to do.

Install

pip install langchain-openterms

What it does

When your LangChain agent interacts with a website, this package checks /.well-known/openterms.json on that domain first. If the site says scraping is denied, the agent gets a clear denial instead of executing and getting blocked or creating legal exposure.

Three ways to use it

1. Wrap a tool (recommended)

OpenTermsGuard wraps any existing tool with a permission check. If the domain denies the action, the tool returns a denial message instead of executing.

from langchain_community.tools import DuckDuckGoSearchRun
from langchain_openterms import OpenTermsGuard

search = DuckDuckGoSearchRun()

# Wraps the search tool: checks "read_content" before each query
guarded_search = OpenTermsGuard(
    tool=search,
    action="read_content",
)

# Use guarded_search in your agent instead of search.
# If a domain denies read_content, the agent gets a message
# explaining why instead of raw results.
result = guarded_search.invoke("https://example.com/pricing")

For strict mode (block if no openterms.json exists):

guarded_search = OpenTermsGuard(
    tool=search,
    action="scrape_data",
    strict=True,  # Deny if openterms.json is absent
)

2. Give the agent a checker tool

OpenTermsChecker is a standalone tool the agent can call to check permissions before deciding what to do.

from langchain_openterms import OpenTermsChecker
from langchain.agents import AgentExecutor, create_openai_functions_agent

checker = OpenTermsChecker()

# Add checker to your agent's tool list
tools = [checker, your_other_tools...]

# The agent can now call:
#   openterms_check("github.com scrape_data")
# and get back a JSON result telling it whether scraping is allowed.

3. Passive logging with a callback

OpenTermsCallbackHandler observes tool invocations and logs permission checks without blocking anything. Useful for auditing.

from langchain_openterms import OpenTermsCallbackHandler

handler = OpenTermsCallbackHandler(
    default_action="read_content",
    on_check=lambda r: print(f"{r['domain']}: {r['allowed']}"),
)

result = agent.invoke(
    {"input": "Research pricing pages"},
    config={"callbacks": [handler]},
)

# After execution, inspect all checks:
for check in handler.checks:
    print(check["domain"], check["allowed"], check.get("receipt"))

With an existing agent

from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_community.tools import DuckDuckGoSearchRun
from langchain_openterms import OpenTermsGuard, OpenTermsChecker

llm = ChatOpenAI(model="gpt-4o")

# Wrap your web tools
search = OpenTermsGuard(tool=DuckDuckGoSearchRun(), action="read_content")
checker = OpenTermsChecker()

prompt = ChatPromptTemplate.from_messages([
    ("system", (
        "You are a research assistant. Before interacting with any website, "
        "use the openterms_check tool to verify what you're allowed to do. "
        "Respect all permission denials."
    )),
    ("human", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"),
])

agent = create_openai_functions_agent(llm, [search, checker], prompt)
executor = AgentExecutor(agent=agent, tools=[search, checker])

result = executor.invoke({"input": "Find pricing info for Stripe's API"})

How it works

  1. Agent invokes a tool with a URL or domain reference
  2. The integration extracts the domain from the input
  3. Fetches https://{domain}/.well-known/openterms.json (cached for 1 hour)
  4. Checks the requested permission (e.g., read_content, scrape_data)
  5. If denied: returns a message explaining the denial
  6. If allowed or unspecified: tool executes normally
  7. Generates an ORS receipt (local, no server call) for audit logging

ORS Receipts

Every permission check can generate a receipt: a lightweight record of what was checked, the result, and a hash of the openterms.json content at the time. These are local objects your application can log however you choose.

from langchain_openterms import OpenTermsClient

client = OpenTermsClient()
result = client.check("example.com", "scrape_data")
receipt = client.receipt("example.com", "scrape_data", result)
# receipt = {
#     "domain": "example.com",
#     "action": "scrape_data",
#     "allowed": False,
#     "checked_at": "2026-04-11T...",
#     "openterms_hash": "a1b2c3..."
# }

Configuration

from langchain_openterms import OpenTermsClient

client = OpenTermsClient(
    cache_ttl=1800,  # Cache openterms.json for 30 minutes (default: 3600)
    timeout=10,      # HTTP timeout in seconds (default: 5)
)

# Pass to any integration component
guard = OpenTermsGuard(tool=my_tool, action="read_content", client=client)
checker = OpenTermsChecker(client=client)

Links

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

langchain_openterms-0.3.1.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

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

langchain_openterms-0.3.1-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file langchain_openterms-0.3.1.tar.gz.

File metadata

  • Download URL: langchain_openterms-0.3.1.tar.gz
  • Upload date:
  • Size: 12.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for langchain_openterms-0.3.1.tar.gz
Algorithm Hash digest
SHA256 e8eb28523e536b8cd312b21a7b8ada64ff190953029b3c44e6e159dc19edfb40
MD5 cb207ff182c48692578fc9666bd842dd
BLAKE2b-256 e46e0ecda8afef11e6e7f5ab66f26b1cc0754a1dfcdd59adfd8d0ce21f03a4bd

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_openterms-0.3.1.tar.gz:

Publisher: publish.yml on jstibal/langchain-openterms

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

File details

Details for the file langchain_openterms-0.3.1-py3-none-any.whl.

File metadata

File hashes

Hashes for langchain_openterms-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a5f359afd747ac0570247e234dfec01413a0ff9d2410773b11480683c992c49a
MD5 27708f87a2211f19b7a3d582b09eda24
BLAKE2b-256 38b1e420bbf3e10b13f9ba4023e4d00bfdaf93df9cb602369db62d9a80c87a0c

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_openterms-0.3.1-py3-none-any.whl:

Publisher: publish.yml on jstibal/langchain-openterms

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