Give your agents
a card
for real work.

You issue a KIFF Card to a named agent. It says which actions the agent may take, under what conditions, and how much. KIFF checks each proposal before your system runs the action, keeps the balance, and lets you revoke the card at any time.

A card narrows actions your domain and permissions already allow. It cannot grant an action on its own. KIFF authorizes; your system executes.

three cards · one named holder
KIFF Card · issued
active
support-agent card-refund · example
may do REFUND_ORDER
only when the order is PAID
up to €5,000 per calendar day
€4,000 used€1,000 remaining
REFUND_ORDER on ord_8812 −€4,000 authorized
Only the owner can change the ceiling or revoke this card.

The €4,000 movement records an authorization. The refund itself runs in your system.

KIFF Card · issued
active
support-agent subscription-plan-change · example
may do CHANGE_PLAN
only when the subscription is ACTIVE
up to 40 changes per day
9 used31 remaining
CHANGE_PLAN on sub_4471 1 change authorized
Only the owner can change the ceiling or revoke this card.

KIFF authorizes the change. Your billing system applies it.

KIFF Card · issued
active
support-agent retention-credit · example
may do ISSUE_STORE_CREDIT
only when the customer is ELIGIBLE
up to €2,000 per calendar day
€750 used€1,250 remaining
ISSUE_STORE_CREDIT for cus_2048 −€250 authorized
Only the owner can change the ceiling or revoke this card.

KIFF authorizes the credit. Your commerce system issues it.

One holder. Separate cards. Give each job its own card. Change or revoke it without touching the others.

a KIFF Card, from issue to revoke

You decide what it may do. The card carries that decision.

When an action requires a card, the agent must present one. The card narrows existing permissions. It never grants new ones.

01 · Issue

Name the holder. Set actions, conditions, ceiling, window and expiry.

02 · Use

Each authorization draws before your system runs the action.

03 · See

See the ceiling, drawn amount and remaining authority.

04 · Change the ceiling

Draws already made still count; raising the ceiling adds only the difference, and the revision records who made the change.

05 · Revoke

Take it back. The next action that requires it is refused.

what this card can do that a payment card cannot
It bounds actions and conditions It knows REFUND_ORDER and PAID. A payment card only knows merchant and amount.
Money is one unit Cap three customer deletions an hour or two deploys a day.
The holder cannot raise it Only an owner can add room. Every change is recorded.
What a KIFF Card can and cannot say →
the queue nobody planned for

Your agent proposes it. A human still clicks it.

Every proposal enters the same queue: open, skim, agree, click. The agent runs faster; deployment still runs on human throughput.

A credential cannot settle whether an action is authorized now. That takes shared state, permissions, approvals, and cumulative limits.

Review the exceptions. Let the card clear the routine. allowed work runs · approval cases wait · limits refuse
the same month, twice
today
agent proposesa person clicks
agent proposesa person clicks
agent proposesa person clicks
agent proposesa person clicks
every one, every month
with KIFF
agent proposesruns
agent proposesruns
agent proposesruns
agent proposesa person
the exception waits for a grant, in the Control Room or your own flow
01 The review is not free Someone reads work the rules could settle.
02 The review stops being one Repetition turns approval into muscle memory.
03 So the agent stays caged A per-call check cannot say what every path has already drawn today.
why the checks you have are not enough

Ten correct decisions can still be a wrong day.

Each check helps. Only the last controls the whole day.

1
Scope the token Refund calls only. Static. It cannot see an earlier refund.
2
Check state in the agent Read the order first. The agent can be talked out of its own check.
3
Decide outside the agent KIFF does this A service answers before execution. It still sees one call, not the day.
4
Count what it has drawn KIFF does this One balance across every run, process, machine and channel the same holder acts through.

Only the fourth sees the day. There is no approve button: more room is a raised limit, and the change is recorded.

what the fourth one has to survive
Two at once The ledger locks the balance before either proceeds.
A retry is not a second refund The same proposal draws once, however often it arrives.
Unreadable is not zero An unreadable balance refuses the action.
Approval draws too A person-approved refund still draws on the day.
What a card can and cannot say →
make reality executable

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.

1 Establish reality Events produce shared state that every actor can read and replay.
2 Define agency Typed actions declare what is possible, which parameters matter, and who has authority.
3 Record consequences KIFF validates before your application executes, then records the result for everyone who follows.
same pattern · different work
order CARTPAIDFULFILLEDRETURNED
invoice ISSUEDAPPROVEDPAIDRECONCILED
claim OPENEDREVIEWEDAPPROVEDSETTLED
case OPENEDASSIGNEDRESOLVEDCLOSED
peopleagentsservicespartnerssystems
guard connects the stack

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.

01, install the guard
your shell
pip install kiff-guard   # or: npm i @kiff/kiff-guard
02, put it in front of the action

Pick your stack. The KIFF side is identical everywhere, the same three-field contract; only the adapter and one attach line change.

agent.py
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 runs
agent.py
from 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)])
agent.py
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): ...
agent.py
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))
agent.py
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))
agent.py
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)])
agent.py
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)])
agent.py
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()
agent.ts
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
agent.py
# 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
shell
# 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.

why a card has one balance

A card is only a card when it counts in one place.

A balance that lived with the agent would reset every time the agent did. Restart it, scale it out, run it from somewhere else, and a ceiling of five a day becomes five per copy. Cloud holds the one balance every run and every machine draws from, together with the state the decision needs. Restarting or scaling the holder does not reset its card; a different holder receives its own card against the same domain.

Explore the real KIFF appFully navigable · sample data
One balance per card Counted across every run, process and machine
Current state What is true now, rebuilt from events
Shared domains One lifecycle every actor understands
Human authority Risky work waits for the right person
One history Every proposal, decision, and result
Build the foundation free. Operate it on Cloud. Cloud meters the operations it runs-never the number of domains, agents, frameworks, or teams that reuse them.
See pricing →
see it in action

Three lines. Your code still runs the action.

One call, before the side effect. KIFF answers; your function returns early or proceeds untouched.

your_app.py
def issue_refund(order, amount):
+ d = kiff.decide("issue_refund", order=order, amount=amount)
+ if not d.allowed:
+ return d # blocked or held, you never execute
payments.refund(order, amount) # your code, unchanged
issue_refund · order 4471 · €42 allowed
Right state, right permission, under the threshold. Runs, and nobody reads it.
issue_refund · order 2287 · €88 refused
Same call, same code path. Refused on the day's authority, and your function never reaches the payment line.
the agent asks for a higher ceiling refused
Its own credential cannot raise its own limit. A limit the agent can raise is not a limit: that is the whole separation.
Run it live, against a real agent →
start with one agent

Issue your first card for one real action.

Choose the holder, an action it already has permission to take, the conditions and a ceiling. Connect Guard where that action runs. KIFF checks the next proposal against the card and records what it drew.

Start with authority for one action. The domain and permissions still decide whether the action itself is legal.

first card one agent
01
Name the holder

The agent's actor id appears on every proposal and on its card.

02
Set the terms

Choose the action, allowed states, ceiling, window and expiry.

03
Connect the action

Guard asks KIFF before your system performs it.

04
Read the statement

See authorizations, the balance remaining and any refusal in activity.

make it yours

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.

install the skill in your agent
Cursor
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.
Kiro
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.
Codex
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.
Claude Code
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.
Copilot
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.
Gemini CLI
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.
Aider
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.
Amp
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.
OpenCode
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.
Windsurf
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"

where teams put the first one

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.

Customer operations
Issue refundsApply creditsCancel ordersChange plans
Cloud & infrastructure
Restart servicesScale resourcesRoll back a deployRotate credentials
Start with your first one →
ask AI about KIFF

Open your assistant with a prompt to read llms-full.txt and answer from it.

one named holder per card

Give it room to work. Keep the right to take that room back.

Issue a card for an action your agent already has permission to take. See each authorization draw on the balance. Change its ceiling or revoke it when the work changes.

Running on your own infrastructure? The framework is open source →