Docs Frameworks
Strands Agents
Status: verified. The adapter ships in
kiff-guard and passes the
conformance suite. The seam was verified against the real
strands-agents package.
Shape: vote (inverted-control). Strands runs the tool itself; its
BeforeToolCallEvent hook only votes — set event.cancel_tool to a
message to block, leave it unset to allow. So the guard uses
observe() / decide_only(), not a run callback. See
how the guard works.
Install
pip install "git+https://github.com/kiffhq/kiff-guard.git#subdirectory=packages/python/kiff-guard"
# plus Strands, the framework you're guarding:
pip install strands-agents
Observe — audit with zero config
from strands import Agent
from kiff_guard import Guard
from kiff_guard.adapters.strands import kiff_hook_provider
guard = Guard(mode="observe") # no client, no tenant needed
agent = Agent(
model=...,
tools=[refund_order, send_email],
hooks=[kiff_hook_provider(guard)],
)
Run the agent as usual, then read the trail:
for r in guard.receipts:
print(r.state, r.tool, r.outcome)
Activate
Derive a starter domain from what you observed, review it, and activate it in the dashboard:
from kiff_guard import export_yaml
print(export_yaml("my-domain", guard.catalog))
Enforce — govern at runtime
Once you have a tenant and an active domain, point the guard at KIFF and
switch to enforce. Only the guard changes:
from kiff_guard import Guard, HTTPClient, ToolMap
from kiff_guard.adapters.strands import kiff_hook_provider
client = HTTPClient(
api_key="kiff_live_...", # mint in the dashboard
tool_map=ToolMap().bind(
"refund_order", action="REFUND_ORDER",
entity_type="Order", entity_arg="order_id"),
)
guard = Guard(client=client, tenant="<tenant>", agent="support", mode="enforce")
agent = Agent(model=..., tools=[refund_order], hooks=[kiff_hook_provider(guard)])
In enforce mode a withheld decision sets event.cancel_tool to the
reason; Strands cancels the call and surfaces the message as a tool
result with an error status. An allowed decision leaves the event
untouched and the tool runs. On a transport error the guard fails closed
(cancels) by default.
The seam (verified)
Strands fires BeforeToolCallEvent before executing a tool;
event.tool_use carries the tool name and input, and
event.cancel_tool: bool | str blocks the call. The guard registers via
a HookProvider attached with Agent(hooks=[...]).
Links
- Adapter code:
kiff_guard/adapters/strands.py - Strands docs: strandsagents.com (Hooks → BeforeToolCallEvent)