aiyoplane-langchain
AEAP Composition Boundary Adapter for LangChain.
A thin wrapper that attaches the AEAP Runtime Decision Point (RDP) to LangChain's tool-invocation surface. Consequential tool executions produce independently verifiable Execution Receipts. The adapter does not alter LangChain's agent, memory, prompt, or retrieval surfaces — only the specific boundary where a tool is about to execute.
pip install aiyoplane-langchain
What this adapter is (and is not)
It is: the shape AEAP takes when attached to a LangChain BaseTool. The underlying authorization logic lives in aiyoplane-mcp-authz; this package distributes that logic into the LangChain ecosystem under LangChain-native idioms.
It is not: a new authorization product. It is not a LangChain plugin that adds features. It is not a LangSmith / LangFuse replacement. It has no feature backlog of its own — if the behavior needs changing, the change belongs in aiyoplane-mcp-authz so every AEAP adapter inherits it.
See the AEAP specification §9 for the Composition Boundary primitive this adapter realizes.
Install
pip install aiyoplane-langchain
# Peer dependencies installed automatically:
# aiyoplane-mcp-authz >= 1.0.1
# langchain-core >= 0.3, < 0.4
Minimal usage
from langchain_core.tools import tool
from aiyoplane_mcp_authz import create_aiyo_mcp_authz, create_local_rdp
from aiyoplane_langchain import wrap_tool
# 1. Define a LangChain tool as you normally would.
@tool
def transfer_funds(amount: int, to_account: str) -> str:
"""Transfer funds between accounts."""
return _actually_transfer(amount, to_account)
# 2. Define the AEAP policy (local RDP for development; HostedRdp for production).
policy = {
"rules": [
{"action_type": "payment", "amount_max": 1_000, "effect": "allow"},
{"action_type": "payment", "amount_max": 10_000, "effect": "escalate"},
{"action_type": "payment", "effect": "block"},
]
}
authz = create_aiyo_mcp_authz(
rdp=create_local_rdp(policy=policy),
tool_config={
"transfer_funds": {
"aiyo_gated": True,
"action": {"type": "payment"},
},
},
)
# 3. Wrap the tool at its Composition Boundary.
guarded_transfer = wrap_tool(
transfer_funds,
authz=authz,
intent_builder=lambda args: {
"type": "payment",
"amount": args["amount"],
"target": args["to_account"],
},
)
# 4. Use the wrapped tool anywhere LangChain accepts a tool.
# On ALLOW: the inner tool runs normally.
# On ESCALATE: aiyoplane_langchain.EscalationRequired is raised.
# On BLOCK: aiyoplane_langchain.BlockedByPolicy is raised; the tool never executes.
Wrapping a whole tool list
The common case is "here are my agent's tools; some of them need AEAP gating."
from aiyoplane_langchain import wrap_tools
all_tools = [search_docs, read_user, transfer_funds, delete_account]
guarded_tools = wrap_tools(
all_tools,
authz=authz,
intent_builders={
"transfer_funds": lambda args: {"type": "payment", "amount": args["amount"]},
"delete_account": lambda args: {"type": "destructive", "target": args["user_id"]},
# search_docs and read_user are omitted — they pass through un-wrapped.
},
)
Tools whose name is not a key in intent_builders pass through unchanged. This is intentional: AEAP gating is an explicit opt-in, not a wholesale wrapper. The Protected Party's policy decides which actions are consequential.
Composition Boundary — what the adapter actually does
The adapter is a wrapper around LangChain's BaseTool._run / _arun. On invocation:
- Intent construction. The adapter calls the user-supplied
intent_builder(tool_args)to produce an AEAP Intent payload. See AEAP §3. - RDP evaluation. The Intent is passed to the
AiyoAuthzmiddleware fromaiyoplane-mcp-authz, which calls the RDP (local or hosted). - Verdict composition.
- ALLOW → the inner tool's
_run/_arunexecutes with the original arguments. The verified Execution Receipt is available for inspection and optionally returned alongside the result (seereturn_receipt=True). - ESCALATE →
EscalationRequiredis raised. The exception carries anescalation_idfor correlation. The LangChain agent / chain decides how to route the escalation. - BLOCK →
BlockedByPolicyis raised. The inner tool never executes.
- ALLOW → the inner tool's
- Fail-closed default. Any ambiguous condition — missing
intent_builder, non-dict Intent, RDP unreachable, RDP exception, misconfiguredtool_config— results inBlockedByPolicy. See AEAP §2.2 invariant 5.
Local vs. hosted RDP
The adapter is RDP-agnostic — it delegates evaluation to the AiyoAuthz middleware, which accepts either a LocalRdp (in-process, for development and self-hosted deployments) or a HostedRdp (connects to api.aiyoplane.com, for managed deployments). Switching is a one-line change in the AiyoAuthz construction; the adapter and the LangChain tool are unchanged.
# Development / self-hosted:
from aiyoplane_mcp_authz import create_local_rdp
authz = create_aiyo_mcp_authz(rdp=create_local_rdp(policy=policy), tool_config={...})
# Production / hosted:
from aiyoplane_mcp_authz import create_hosted_rdp
authz = create_aiyo_mcp_authz(
rdp=create_hosted_rdp(api_key="aiyo_live_..."),
tool_config={...},
)
API reference
wrap_tool(tool, *, authz, intent_builder, tool_name_for_authz=None, return_receipt=False)
Wrap a single BaseTool. Returns an AiyoLangChainTool.
tool— the original LangChain toolauthz— anAiyoAuthzinstanceintent_builder— a callable(tool_args: dict) -> dicttool_name_for_authz— override for theauthz.tool_configkey; defaults totool.namereturn_receipt— ifTrue, the wrapped tool returns{"result": ..., "aeap_receipt": ...}on ALLOW
wrap_tools(tools, *, authz, intent_builders, return_receipt=False)
Wrap a collection in one call. Tools whose name is not a key in intent_builders pass through unchanged.
AiyoLangChainTool
The BaseTool subclass produced by wrap_tool. You rarely need to construct this directly.
Exceptions
AiyoLangChainError— base classAdapterConfigError— adapter configuration is invalid (missingtool_configentry, badintent_builder)BlockedByPolicy— RDP returned BLOCK; the tool did not executeEscalationRequired— RDP returned ESCALATE; the tool call is held pending resolution
License
Apache License 2.0. See LICENSE for the full text.
Links
- AEAP specification: https://github.com/aiyoplane/aeap
- Underlying implementation:
aiyoplane-mcp-authz - Node sibling:
@aiyoplane/langchainon npm - Related adapters:
aiyoplane-langgraph(same install model, graph-node composition) - Trust surface: https://aiyoplane.com/trust
- Issues: https://github.com/aiyoplane/langchain-python/issues
LangChain is a trademark of LangChain, Inc. This package is an independent AEAP Composition Boundary Adapter and is not affiliated with or endorsed by LangChain, Inc.
Verify First. Execute Second.
Metadata
Release files for aiyoplane-langchain 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aiyoplane_langchain-1.0.0.tar.gz | 16.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aiyoplane_langchain-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.3 kB
Release files / aiyoplane_langchain-1.0.0.tar.gz
| Download URL | aiyoplane_langchain-1.0.0.tar.gz |
|---|---|
| Size | 16.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c8eb19c9a02c1d049717982f94225f533b5e6cbfed8d7d84600c6e9fdb4c20b8
|
|
BLAKE2b-256 checksum How to use checksums |
150596cf8e3c0e274223384ee06dd564ba1781eb6c3e142b42d885e5c9fc6bda
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / aiyoplane_langchain-1.0.0-py3-none-any.whl
| Download URL | aiyoplane_langchain-1.0.0-py3-none-any.whl |
|---|---|
| Size | 15.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2942a430536d248115dcba16cb8ea32528b723336cfff14740ee005659ddb7e6
|
|
BLAKE2b-256 checksum How to use checksums |
b64dde886dff85a9495a974386dd6db7f2e96a3e6b043beaa1f18125428b0269
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|