| Requirement | Version |
|---|---|
| Agent Assembly Python SDK (agent-assembly) | >= 0.0.1rc6 |
Install:
uv add agent-assembly==0.0.1rc6
# or
pip install agent-assembly==0.0.1rc6The simplest Agent Assembly integration — no AI framework required.
Demonstrates how to add Agent Assembly governance to plain Python functions using the minimal governed() wrapper helper.
- Initializing Agent Assembly with
init_assembly(). - Wrapping any Python function with governance using
governed(). - Two allowed tool calls (
compute_sum,fetch_stock_price). - Two denied tool calls (
send_http_request,write_to_disk— blocked by policy). - That the wrapped function body never executes when governance denies it.
- How this
governed()pattern relates to the framework path: thellamaindex-tool-policyexample governs tool calls by registering the nativeLlamaIndexAdapter(auto-wired byinit_assembly()) instead of wrapping each callable.
| Requirement | Version |
|---|---|
| Python | >= 3.12 |
| uv | latest |
| Agent Assembly Python SDK | >= 0.0.1rc6 |
No API key, no gateway, and no AI framework are required.
cd python/custom-tool-policy
uv sync --extra devuv run python src/main.py==============================================================
Agent Assembly — Custom Tool Policy Demo
(no AI framework required)
==============================================================
Initializing Agent Assembly (gateway: http://localhost:8080, sdk-only mode)...
Agent: custom-tool-demo-agent
Gateway: http://localhost:8080
Mode: sdk-only (offline demo)
Policy rules (local simulation of gateway policy):
DENY — send_http_request, write_to_disk (network / disk writes)
ALLOW — everything else
Running governed tool calls:
--------------------------------------------
→ compute_sum({'a': 12.5, 'b': 7.3})
✅ ALLOWED — 19.8
→ fetch_stock_price({'ticker': 'AAPL'})
✅ ALLOWED — $211.30 (mock)
→ send_http_request({'url': 'https://example.com/data', 'method': 'POST'})
❌ BLOCKED — Tool 'send_http_request' is blocked by policy rule 'deny_network_and_disk_writes'.
→ write_to_disk({'path': '/etc/cron.d/evil', 'content': 'rm -rf /'})
❌ BLOCKED — Tool 'write_to_disk' is blocked by policy rule 'deny_network_and_disk_writes'.
uv run pytest tests/ -vLocalPolicyEngine is a stand-in for the gateway: it answers the
check_tool_start contract (the GovernanceInterceptor protocol in
agent_assembly.adapters) in-process so this demo runs fully offline. Reaching
the real gateway in production is not a matter of passing ctx.client to
governed().
⚠️ Do not passctx.clientas the interceptor.ctx.clientis a bareGatewayClient— it has nocheck_tool_startmethod. Wire it intogoverned()andAssemblyCallbackHandler.on_tool_startfinds no check, returns without raising, and allows every tool: governance is silently disabled (fail-open).ctx.clientis for agent metadata and audit emission, not pre-execution policy checks.
The supported production path is a framework adapter. Run your tools through
a supported AI framework (LangChain, LlamaIndex, CrewAI, …). On startup
init_assembly() auto-detects the installed adapter and wires the real
gateway-backed interceptor into that framework's tool-execution path, so every
tool call is checked against the gateway with no per-tool wrapper and no
interceptor argument of your own. The llamaindex-tool-policy example shows
this end to end — it registers the native LlamaIndexAdapter and lets
init_assembly() supply the live interceptor:
from agent_assembly import init_assembly
# init_assembly() auto-detects the installed framework adapter and wires the
# real gateway-backed interceptor into its tool-execution path. Define tools the
# way the framework expects (e.g. a LlamaIndex FunctionTool); every call is then
# governed against the gateway — no governed() wrapper, no ctx.client.
with init_assembly(gateway_url="http://localhost:8080", agent_id="my-agent"):
... # run your framework agent; its tool calls are now governedSDK gap. For the bare no-framework pattern this example teaches, the SDK exposes no public drop-in interceptor that talks to a real gateway: the gateway-backed interceptor (
RuntimeQueryInterceptor) is internal and is only wired through a registered framework adapter, and the publicGovernanceInterceptorprotocol is just thecheck_tool_startcontract thatLocalPolicyEngineimplements here. To govern plain callables against a real gateway today, adopt a supported framework adapter (above), or supply your own object that implementscheck_tool_startand answers from the gateway itself — neverctx.client.
| Problem | Fix |
|---|---|
ModuleNotFoundError: agent_assembly |
Run uv sync first |
ToolExecutionBlockedError in tests |
Expected — the deny rules for send_http_request and write_to_disk are intentional |