Agent approval workflows

Approval for AI agents, one card per change.

Klingbar runs crews of AI agents that watch your business and report in Slack. Each agent is a persona, and its standing policy is short: reads are free, and every change is proposed as a card that waits for an approver. A person decides it in Slack, the Home tab, or on the web, and the decision goes on the record.

#supportMonday, 10:41 AM
SupportApp10:41 AM

One customer was charged twice for order 10482. The second charge is the duplicate. Details are in the thread.

AP-41 — Refund the duplicate charge on order 10482

Refund the second $64.00 charge to the original card, then reply to the customer with the refund confirmation.

Support · proposed Mon · expires Thu (72h) · react, tap, or reply approve / deny <reason>
ApproveDeny…
An illustration of a pending card. Nothing is refunded until an approver says yes.
The rule

Reads are free. Changes wait.

A persona reads whatever you give it access to — a database replica, a support inbox, a repository — without asking. When it wants to change something, it writes the change down: a one-line title, exactly what it will do, and the command, recipients, or pull request involved. The box gives that proposal an id and posts it to the persona's channel as a card.

Approve it, and the persona is resumed with one instruction: make exactly that change, then report back. Deny it, with a reason if you like, and it does not happen. Leave it, and after 72 hours (the crew's approval_expiry_hours) it expires and does not happen either.

What goes on a card
send
Anything addressed to a person outside the crew.
push
Code or configuration to a branch other people use.
edit
A record in a system you gave the persona access to.
run
A command that alters state or spends money.
free
Reading, searching, summarizing, and drafting.
Policy

One free zone, one ceiling

Two settings move the default, per persona. A git free zone lets a persona commit and push inside its own workspace, to one named branch, without a card — useful when it keeps notes in a repository or opens pull requests you review anyway. A send ceiling goes the other way: anything addressed to a person outside the crew is composed as a draft and never sent, so an approved card means "write the draft", not "send it".

Both are written into the persona's prompt as its operating contract. They are not a sandbox: the engines run with their permission prompts turned off, so the real limit on a persona is the access you give it — the secrets it lists, its workspace, and its engine login. Give each persona the least it needs for its job.

[personas.support.policy]
send_ceiling = "draft_only"

[personas.notes.policy]
git_in_workspace = "free"
push_branch      = "crew/notes"

Set on a persona's page on klingbar.com. The box receives it in crew.toml and writes it into that persona's prompt.

Three places, one decision

Decide in the channel, the Home tab, or the web

In the channel, tap Approve or Deny, react with a check or a cross, or reply "approve" or "deny" with a reason. You also get one Slack Home tab across every crew you belong to in that workspace, listing their open cards, questions, and proposed learnings, with the same controls. And the cards page on klingbar.com shows every card, pending and decided.

The first decision is the one that counts: a tap after someone has already approved in the channel is dropped, not doubled. The decision records who made it and where — a button, a reply, the Home tab, or the web.

Home · Acme crewrefreshed 10:52 AM
Waiting on you1 card · 1 question · 1 learning
AP-41 — Refund the duplicate charge on order 10482
ApproveDeny…
Revenue asks: count trial conversions by signup date or by charge date?
L-8 — proposed learning from Revenue
An illustration of one person's Home tab for one crew. Someone who is not an approver sees the list without the controls.
One message, updated in place

The card says what happened to it

A card is one Slack message, and it changes as the decision plays out. Approved, it names the approver and the time and says the change is executing. Executed, it gives the time and links the report of what was done. Denied, it names who denied it and why. Unanswered, it says it expired without a decision. If an approved change fails, the card says that too, with the error.

AP-41, in each state it can reach
pending
Support · proposed Mon · expires Thu (72h)
approved
Approved by Dana · 10:58 AM · executing…
executed
Executed · 11:01 AM · see the report
denied
Denied by Sam · 11:03 AM — wrong order number
expired
Expired Thu after 72h without a decision
Who decides

The people behind the buttons

The approver list

Each crew has one list of approvers, by Slack user. On Klingbar's Slack app the list must name at least one; on a crew's own app, an empty list lets anyone in the channel decide. A member links their Slack identity once, with a one-time code Klingbar's Slack app sends by direct message, and anyone not on the list sees cards without controls.

The owner

The crew owner may decide from klingbar.com without linking Slack, and that is recorded as a web decision by the owner. No decision asks for a passkey step-up.

Questions and learnings

A run's questions are answered in the same three places, and the first answer resumes the run. Proposed learnings are accepted or rejected by an approver before any prompt carries them.

Boundaries

What the web deliberately cannot do

klingbar.com talks to a box through a closed vocabulary of 17 verbs — run, pause, resume, decide, answer, and a dozen more — each with a closed set of parameters. It is not a shell: the box builds every argument list itself from a verb it recognizes, and no verb has a slot for a key or a token. A secret travels sealed, as an opaque parameter only the box can open.

There is no verb for creating an approval: cards are minted by the box from what a persona proposed, and only the decision travels back. Each crew has its own approver list. And the web shows what the box reported — an approved card reads approved until the box says it executed, and anything unreported reads "not reported", never a green nobody measured.

Related reading: what runs on your box and what crosses the wire, the guide to AI agent audit trails, and a crew's structure as one versioned document, where the approver list lives.

Frequently asked

What is a human approval workflow for AI agents?

It is a rule that a change an agent proposes does not happen until a named person approves that exact change. In Klingbar the rule is short: reads are free, and a persona proposes every change as a card and waits for an approver.

Which actions need a card?

Any change: sending a message, pushing code, editing a record, or running a command that alters something. Reading, searching, and drafting do not. A persona can be given one narrower free zone, such as committing and pushing to one named branch, or a ceiling, such as composing customer email as drafts that are never sent.

Where do approvers decide?

On the card in Slack — a button, a reaction, or a reply — on your Slack Home tab, or on klingbar.com. The first decision is the one that counts, and the card records who decided and where.

What happens if nobody decides?

Nothing. A card expires after 72 hours by default, a setting each crew can change, and its Slack message updates in place to say so. A decision made on klingbar.com stays valid for as long as the card does, so a box that was briefly offline still receives it.

Is there a passkey or second factor on each decision?

No. What matters is who decides: a member acts only with a linked Slack identity on the crew's approver list, and the crew owner may also act from klingbar.com. Every command's transitions are written to an append-only audit trail in the same transaction as the change.

Decide what needs you, and only that

Klingbar is free during early access. You bring a machine and your own engine logins; the decisions happen in the Slack you already use. What that means.

Request early access