Stop manually
approving every
agent action.
Tool access is not authority. A credential lets an agent call refund. It cannot say whether this refund is valid now or how much the agent has already authorized today. KIFF checks the proposed action against live state, permissions, and remaining limits before your code runs it.
Work inside the boundary runs without anyone reading it. Only the exceptions reach a person. Your rules decide, not another model's opinion.
Drop the MIT Guard into an existing agent, or call Cloud over HTTP. KIFF constrains existing authority; it does not grant permission or execute the action.
kiffer, v., to properly enjoy something. That is what a bounded agent is for. How limits work →
Your agent proposes it. A human still clicks it.
The work moved into a queue: open, skim, agree, click. When every proposal waits for the same manual step, deployment still runs on human throughput.
A tool credential cannot settle whether this action is authorized now. That takes shared state, permissions, approvals, and cumulative limits across the operation.
Review the exceptions. Let the boundary clear the routine. allowed work runs · approval cases wait · limits refuseTen correct decisions can still be a wrong day.
Every team building agents arrives at some version of this. Each step is better than the last.
Only the fourth is a fact about the day rather than the call, which is why no per-call check can reproduce it. There is no approve button when it refuses, by design: more room is a raised limit, and that leaves a record of somebody raising it.
Turn business truth into a system agents can act through.
Model the lifecycle once: what is true now, what actions are possible, and who has authority. Every agent you add next reads the same rule.
Different frameworks. Same reality.
Keep Agno, LangGraph, OpenAI, Google ADK, Strands, n8n, or your own stack. KIFF Guard connects their pre-execution seam to the same operational domain, so state, rules, and history survive every model and framework change.
pip install kiff-guard # or: npm i @kiff/kiff-guardPick your stack. The KIFF side is identical everywhere, the same three-field contract; only the adapter and one attach line change.
from kiff_guard import Guard, HTTPClient, ToolMap
from kiff_guard.adapters.agno import agno_hook
tm = ToolMap().bind("refund_order", action="REFUND_ORDER",
entity_type="Order", entity_arg="order_id")
guard = Guard(client=HTTPClient(api_key=KEY, tool_map=tm),
tenant="acme", agent="refunds", mode="enforce")
guard.connect(adapter="agno")
agent = Agent(model=..., tools=[refund_order],
tool_hooks=[agno_hook(guard)]) # decides before the tool runsfrom kiff_guard import Guard, HTTPClient, ToolMap
from kiff_guard.adapters.langgraph import kiff_wrap_tool_call
tm = ToolMap().bind("refund_order", action="REFUND_ORDER",
entity_type="Order", entity_arg="order_id")
guard = Guard(client=HTTPClient(api_key=KEY, tool_map=tm),
tenant="acme", agent="refunds", mode="enforce")
guard.connect(adapter="langgraph")
agent = create_agent(model=..., tools=[refund_order],
middleware=[kiff_wrap_tool_call(guard)])from kiff_guard import Guard, HTTPClient, ToolMap
from kiff_guard.adapters.openai_agents import kiff_tool_input_guardrail
tm = ToolMap().bind("refund_order", action="REFUND_ORDER",
entity_type="Order", entity_arg="order_id")
guard = Guard(client=HTTPClient(api_key=KEY, tool_map=tm),
tenant="acme", agent="refunds", mode="enforce")
guard.connect(adapter="openai-agents")
@function_tool(tool_input_guardrails=[kiff_tool_input_guardrail(guard)])
def refund_order(order_id: str, amount: int, reason: str): ...from kiff_guard import Guard, HTTPClient, ToolMap
from kiff_guard.adapters.google_adk import kiff_before_tool_callback
tm = ToolMap().bind("refund_order", action="REFUND_ORDER",
entity_type="Order", entity_arg="order_id")
guard = Guard(client=HTTPClient(api_key=KEY, tool_map=tm),
tenant="acme", agent="refunds", mode="enforce")
guard.connect(adapter="google-adk")
agent = Agent(tools=[refund_order],
before_tool_callback=kiff_before_tool_callback(guard))from kiff_guard import Guard, HTTPClient, ToolMap
from kiff_guard.adapters.pydantic_ai import kiff_before_tool_execute
tm = ToolMap().bind("refund_order", action="REFUND_ORDER",
entity_type="Order", entity_arg="order_id")
guard = Guard(client=HTTPClient(api_key=KEY, tool_map=tm),
tenant="acme", agent="refunds", mode="enforce")
guard.connect(adapter="pydantic-ai")
agent = Agent(model=...,
before_tool_execute=kiff_before_tool_execute(guard))from kiff_guard import Guard, HTTPClient, ToolMap
from kiff_guard.adapters.strands import kiff_hook_provider
tm = ToolMap().bind("refund_order", action="REFUND_ORDER",
entity_type="Order", entity_arg="order_id")
guard = Guard(client=HTTPClient(api_key=KEY, tool_map=tm),
tenant="acme", agent="refunds", mode="enforce")
guard.connect(adapter="strands")
agent = Agent(model=..., tools=[refund_order],
hooks=[kiff_hook_provider(guard)])from kiff_guard import Guard, HTTPClient, ToolMap
from kiff_guard.adapters.microsoft_agent_framework import kiff_guard_middleware
tm = ToolMap().bind("refund_order", action="REFUND_ORDER",
entity_type="Order", entity_arg="order_id")
guard = Guard(client=HTTPClient(api_key=KEY, tool_map=tm),
tenant="acme", agent="refunds", mode="enforce")
guard.connect(adapter="ms-agent-framework")
agent = Agent(tools=[refund_order],
middleware=[kiff_guard_middleware(guard)])from kiff_guard import Guard, HTTPClient, ToolMap
from kiff_guard.adapters.hermes import register_kiff_guard
tm = ToolMap().bind("refund_order", action="REFUND_ORDER",
entity_type="Order", entity_arg="order_id")
guard = Guard(client=HTTPClient(api_key=KEY, tool_map=tm),
tenant="acme", agent="refunds", mode="enforce")
guard.connect(adapter="hermes")
register_kiff_guard(ctx, guard) # in your Hermes plugin's register()import { Guard, HTTPClient, ToolMap } from "@kiff/kiff-guard";
import { registerKiffGuard } from "@kiff/kiff-guard/adapters/openclaw";
const tm = new ToolMap().bind("refund_order", {
action: "REFUND_ORDER", entityType: "Order", entityArg: "order_id" });
const client = new HTTPClient({ apiKey: KEY, toolMap: tm });
const guard = new Guard({ client, tenant: "acme", agent: "refunds", mode: "enforce" });
registerKiffGuard(ctx, guard); // in your OpenClaw plugin# No adapter needed. Wrap the one function that moves money.
def issue_refund(order, amount):
d = kiff.decide("REFUND_ORDER", entity=order, amount=amount)
if not d.allowed:
return d # blocked or held, never execute
payments.refund(order, amount) # your code, unchanged# No SDK. Any language. POST the proposed action; act only on "allowed".
curl -s https://api.kiff.dev/v1/proposals/decide \
-H "Authorization: Bearer $KIFF_KEY" -H "Content-Type: application/json" \
-d '{"id":"rd-4471","entity_id":"order-4471","entity_type":"Order",
"action_name":"REFUND_ORDER","actor_id":"refunds",
"parameters":{"amount":8400,"reason":"damaged"}}'
# -> {"outcome":"allowed"} then POST .../execute for a signed receipt// same three-field contract on every stack: entity + action + parameters -> one verdict.
A limit needs one place to count.
To answer "may this run", the boundary needs the current state and one balance every path draws from. That is what Cloud holds, and why the next agent inherits the rule instead of rebuilding it.
Three lines. Your code still runs the action.
One call, before the side effect. KIFF answers; your function returns early or proceeds untouched.
Put a boundary around the next action you ship.
Bring one consequential action in your existing agent and application. We model the minimum operational domain around it, connect Guard and Cloud, and leave a shared reality for the next agent.
Thirty minutes, founder-led. Bring a repository or the shape of your setup; you keep the findings whether or not KIFF is the right answer.
Which consequential actions your agents can reach today.
Where nothing on the path is able to say no.
What you could produce if a customer or regulator asked.
A clear view of the gap, whether or not that involves us.
Let your coding agent define the operational reality.
The guard connects your runtime. The domain is the contract it decides against, install the KIFF domain skill and your coding agent writes and extends your kiff.yaml against the real grammar: states, approvals, permissions, executors.
curl -fsSL https://kiff.dev/skills/kiff-domains.md \ -o .cursor/rules/kiff-domains.mdc
Instructions for your agent
Set up the KIFF domain skill in this project: run `curl -fsSL https://kiff.dev/skills/kiff-domains.md -o .cursor/rules/kiff-domains.mdc` to add the skill, read it, then help me author a kiff.yaml domain for my riskiest action (states, actions, approvals, permissions, executors) and connect it to KIFF Cloud, validate with POST /v1/me/domain/validate, then PUT /v1/me/domain.
mkdir -p .kiro/skills/kiff-domains && curl -fsSL https://kiff.dev/skills/kiff-domains.md \ -o .kiro/skills/kiff-domains/SKILL.md
Instructions for your agent
Set up the KIFF domain skill in this project: run `mkdir -p .kiro/skills/kiff-domains && curl -fsSL https://kiff.dev/skills/kiff-domains.md -o .kiro/skills/kiff-domains/SKILL.md` to add the skill, read it, then help me author a kiff.yaml domain for my riskiest action (states, actions, approvals, permissions, executors) and connect it to KIFF Cloud, validate with POST /v1/me/domain/validate, then PUT /v1/me/domain.
curl -fsSL https://kiff.dev/skills/kiff-domains.md >> AGENTS.md
Instructions for your agent
Set up the KIFF domain skill in this project: run `curl -fsSL https://kiff.dev/skills/kiff-domains.md >> AGENTS.md` to add the skill, read it, then help me author a kiff.yaml domain for my riskiest action (states, actions, approvals, permissions, executors) and connect it to KIFF Cloud, validate with POST /v1/me/domain/validate, then PUT /v1/me/domain.
mkdir -p ~/.claude/skills/kiff-domains && curl -fsSL https://kiff.dev/skills/kiff-domains.md \ -o ~/.claude/skills/kiff-domains/SKILL.md
Instructions for your agent
Set up the KIFF domain skill in this project: run `mkdir -p ~/.claude/skills/kiff-domains && curl -fsSL https://kiff.dev/skills/kiff-domains.md -o ~/.claude/skills/kiff-domains/SKILL.md` to add the skill, read it, then help me author a kiff.yaml domain for my riskiest action (states, actions, approvals, permissions, executors) and connect it to KIFF Cloud, validate with POST /v1/me/domain/validate, then PUT /v1/me/domain.
mkdir -p ~/.copilot/skills/kiff-domains && curl -fsSL https://kiff.dev/skills/kiff-domains.md \ -o ~/.copilot/skills/kiff-domains/SKILL.md
Instructions for your agent
Set up the KIFF domain skill in this project: run `mkdir -p ~/.copilot/skills/kiff-domains && curl -fsSL https://kiff.dev/skills/kiff-domains.md -o ~/.copilot/skills/kiff-domains/SKILL.md` to add the skill, read it, then help me author a kiff.yaml domain for my riskiest action (states, actions, approvals, permissions, executors) and connect it to KIFF Cloud, validate with POST /v1/me/domain/validate, then PUT /v1/me/domain.
curl -fsSL https://kiff.dev/skills/kiff-domains.md >> GEMINI.md
Instructions for your agent
Set up the KIFF domain skill in this project: run `curl -fsSL https://kiff.dev/skills/kiff-domains.md >> GEMINI.md` to add the skill, read it, then help me author a kiff.yaml domain for my riskiest action (states, actions, approvals, permissions, executors) and connect it to KIFF Cloud, validate with POST /v1/me/domain/validate, then PUT /v1/me/domain.
curl -fsSL https://kiff.dev/skills/kiff-domains.md >> AGENTS.md
Instructions for your agent
Set up the KIFF domain skill in this project: run `curl -fsSL https://kiff.dev/skills/kiff-domains.md >> AGENTS.md` to add the skill, read it, then help me author a kiff.yaml domain for my riskiest action (states, actions, approvals, permissions, executors) and connect it to KIFF Cloud, validate with POST /v1/me/domain/validate, then PUT /v1/me/domain.
curl -fsSL https://kiff.dev/skills/kiff-domains.md >> AGENTS.md
Instructions for your agent
Set up the KIFF domain skill in this project: run `curl -fsSL https://kiff.dev/skills/kiff-domains.md >> AGENTS.md` to add the skill, read it, then help me author a kiff.yaml domain for my riskiest action (states, actions, approvals, permissions, executors) and connect it to KIFF Cloud, validate with POST /v1/me/domain/validate, then PUT /v1/me/domain.
curl -fsSL https://kiff.dev/skills/kiff-domains.md >> AGENTS.md
Instructions for your agent
Set up the KIFF domain skill in this project: run `curl -fsSL https://kiff.dev/skills/kiff-domains.md >> AGENTS.md` to add the skill, read it, then help me author a kiff.yaml domain for my riskiest action (states, actions, approvals, permissions, executors) and connect it to KIFF Cloud, validate with POST /v1/me/domain/validate, then PUT /v1/me/domain.
mkdir -p .windsurf/rules && curl -fsSL https://kiff.dev/skills/kiff-domains.md \ -o .windsurf/rules/kiff-domains.md
Instructions for your agent
Set up the KIFF domain skill in this project: run `mkdir -p .windsurf/rules && curl -fsSL https://kiff.dev/skills/kiff-domains.md -o .windsurf/rules/kiff-domains.md` to add the skill, read it, then help me author a kiff.yaml domain for my riskiest action (states, actions, approvals, permissions, executors) and connect it to KIFF Cloud, validate with POST /v1/me/domain/validate, then PUT /v1/me/domain.
// then ask your agent: "add an ISSUE_CREDIT action to the refund domain, PAID-only"
Two places an agent is already acting.
Not a list of markets. These are the two where the action is already being taken without a person, and the total is countable, euros in the first, how many times in the second. Start with one action in one of them.
Open your assistant with a prompt to read llms-full.txt and answer from it.
Start with the action you review most.
Run the boundary against your own traffic. See which proposals it would allow, hold, or refuse, then set the ceiling from your evidence. Add the next action to the same operational domain instead of rebuilding state, authority, approvals, and history.
Running on your own infrastructure? The framework is open source →