Skip to content

webpro255/langchain-agentlock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

langchain-agentlock

AgentLock authorization middleware for LangChain tool calls.

Every tool call is checked against an AuthorizationGate before it runs, and the tool executes only on a valid single-use token. See AgentLock for the permission model.

Install

pip install langchain-agentlock

This pulls in agentlock and langchain-core.

Usage

Three integration surfaces.

1. wrap_tool and AgentLockToolkit

Wrap existing BaseTool instances:

from agentlock import AgentLockPermissions, AuthorizationGate
from langchain_core.tools import StructuredTool
from langchain_agentlock import wrap_tool

gate = AuthorizationGate()

search = StructuredTool.from_function(
    func=my_search, name="search", description="Search the web"
)

protected = wrap_tool(
    search,
    gate,
    AgentLockPermissions(
        risk_level="low",
        requires_auth=False,
        allowed_roles=["analyst"],
    ),
    default_role="analyst",
)

protected.invoke({"query": "agentlock"})

wrap_tool registers the permissions on the gate for you. AgentLockToolkit does the same across a list of tools, taking either one permission block for all of them or a mapping from tool name to permissions:

from langchain_agentlock import AgentLockToolkit

kit = AgentLockToolkit(
    [search, send_email],
    gate,
    {"search": read_perms, "send_email": write_perms},
    default_role="analyst",
)

tools = kit.get_tools()

A tool missing from a per-tool mapping falls back to an entry keyed "*" if you provide one, and otherwise raises KeyError.

2. @authorized_tool

Build an authorized tool directly from a function. gate is keyword-only:

from langchain_agentlock import authorized_tool

@authorized_tool(gate=gate, risk_level="high", allowed_roles=["admin"])
def delete_account(account_id: str) -> str:
    ...

It mirrors langchain_core.tools.tool and accepts the same schema arguments, plus the permission fields (risk_level, requires_auth, allowed_roles, rate_limit, data_policy, scope, audit, session, human_approval), or a prebuilt permissions= block.

3. AgentLockCallbackHandler

Authorize through LangChain callbacks, without wrapping the tools:

from langchain_agentlock import AgentLockCallbackHandler

handler = AgentLockCallbackHandler(gate, mode="enforce")  # or mode="audit"
agent.invoke({"input": "..."}, config={"callbacks": [handler]})

mode="enforce" raises DeniedError on a deny so LangChain aborts the call. mode="audit" records the decision and never raises, which is useful for dry-runs. AsyncAgentLockCallbackHandler is the async equivalent.

Passing identity

The gate needs to know who is calling. Supply it per call as reserved kwargs in the tool input:

protected.invoke({
    "query": "x",
    "_agentlock_role": "admin",
    "_agentlock_user_id": "u1",
})

or through config metadata, which survives args_schema validation:

protected.invoke({"query": "x"}, config={"metadata": {
    "agentlock_role": "admin",
    "agentlock_user_id": "u1",
}})

Reserved kwargs (_agentlock_user_id, _agentlock_role, _agentlock_session_id, _agentlock_metadata) are stripped before the inner tool sees them. Anything not supplied falls back to the default_user_id, default_role, and default_session_id given at wrap time. Pass context_extractor= to resolve identity some other way.

Migrating from agentlock.integrations.langchain

Through v1.4, AgentLock core also shipped a LangChain integration. Core removed it in v1.5 and this package is where it lives now:

  • Replace pip install "agentlock[langchain]" with pip install langchain-agentlock.
  • Import wrap_tool and AgentLockToolkit from langchain_agentlock rather than agentlock.integrations.langchain.
  • AgentLockToolWrapper has no public counterpart here. Use wrap_tool or AgentLockToolkit.

This package is a reimplementation, not the relocated module, so check the signatures above rather than assuming the import path is the only thing that changed.

Development

pip install -e ".[dev]"
pytest

Licensing

This package is Apache 2.0.

It depends on AgentLock, which is licensed AGPL-3.0-or-later from v1.3.0 onward, and this package requires agentlock>=1.5. Installing this package therefore pulls in AGPL code, and combined use is subject to the AGPL: if you run it in a network service or distribute software built on it, the AGPL's terms apply to the combined work. Commercial licenses for AgentLock that remove the AGPL obligations are available at licensing@agentlock.dev.

Read the AGPL and take your own advice on what it requires of you. This note is a pointer, not legal advice.

Contributors

Languages