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.
pip install langchain-agentlockThis pulls in agentlock and langchain-core.
Three integration surfaces.
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.
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.
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.
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.
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]"withpip install langchain-agentlock. - Import
wrap_toolandAgentLockToolkitfromlangchain_agentlockrather thanagentlock.integrations.langchain. AgentLockToolWrapperhas no public counterpart here. Usewrap_toolorAgentLockToolkit.
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.
pip install -e ".[dev]"
pytestThis 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.