> ## Documentation Index
> Fetch the complete documentation index at: https://veriqa.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Approving AI-agent actions

> Human consent on a surface the agent does not control: what the product already has for it and what this construction still lacks.

A software agent acts on a person's behalf, and someone has to say "yes" to the risky part of that
work — consent that is worth little if it is collected on the very screen the agent controls. Why
this matters and for whom is covered on the
[Approving AI-agent actions](https://veriqa.app/whats-next/agent-approvals?lang=en) page. Here is
the engineering side.

## What it builds on

The scenario needs no separate protocol: confirming an action is the same transaction as
confirming a sign-in, only with a different purpose. A transaction with an explicit state and a
single outcome, a message in a trusted channel, the person's answer and an entry in the audit
trail — all of it already exists in Veriqa's core.

For confirming an action rather than a sign-in, the product has:

1. **Server-to-server creation of a confirmation transaction.** The application calls
   `POST /api/transaction/confirmation`, authenticating with client credentials — no OIDC request
   and no user redirect. The response carries the entry point for the person: the channel's deep link and
   the same address as a QR image, with a "Powered by Veriqa" attribution strip under the code. The
   application reads the outcome with
   `GET /api/transaction/{id}/result`.
2. **Concrete wording of the confirmation.** The request names a declared action type
   (`action_type`), and the person sees not "confirm sign-in" but that action's message: which
   action, over what, with which parameters.
3. **A safe way to carry the action's data.** Free-form text from the application never reaches
   the user's message — that is a direct route to substituting the meaning of the confirmation. The
   data travels in typed slots (`slot_values`) against the schema declared for the action type and
   is validated before the transaction is created.

## Available today: an agent whose tools you know

When you build the agent yourself and its tools are known in advance, nothing more is needed. The
approval goes where the tools are invoked, not into the prompt:

1. Each tool with consequences gets an **approval policy** in your code: which declared action type
   asks the person, and which arguments of the call fill its slots.
2. The code that invokes tools checks the policy. For such a tool it creates the confirmation, shows
   or sends its entry point, and waits for the outcome.
3. The tool runs only on `confirmed`. On `declined` or `expired` the harness returns a refusal as the
   result of the call, the same way it reports any other failed call to the model.

Whatever the model decides to call, a tool with a policy does not run without a confirmed
transaction. The person reads the slot values of a declared action type, never text the agent wrote.

The runnable example is `samples/dotnet/inproc/agent-approval` in the repository. A support agent
handles a refund ticket with three tools: `lookup_order` and `send_customer_email` run on their own,
while every `refund_payment` call waits for a person to approve it in Telegram. The run log records who
approved. For a single destructive action in an ordinary application — deleting a project, closing an
account — see `samples/dotnet/inproc/step-up`: there the backend also checks that the person who
confirmed is the owner of the account (`expected_identities`).

For a harness whose tools you do not write, `samples/claude-code` shows the same approval plugged
into Claude Code through its hooks — see [Claude Code mod](/docs/samples/showcase/claude-code).

## What does not exist today

What is missing is the generic layer for agents whose tools the integrator does not write — agent
platforms and harnesses where an approval should plug in without code of your own:

* **a vocabulary of actions** — a shared language for "what are we confirming", rather than a
  free-form set of action types per integrator;
* **an integration surface** for agent platforms and tool protocols, such as an approval step a
  tool server declares by itself;
* **approval policies** around confirmations: what always requires a human, what only above a
  threshold, what can be granted once and reused.

## Where its limits are

The scenario inherits the boundary of the rest of Veriqa: confirmation rests on the person's
trusted channel and on the API of that channel's platform.

<Warning>
  This is a strong and convenient step for scenarios where such trust is appropriate, but **not
  cryptographic proof of intent**. Taking part in the scheme does not turn a messenger into a
  hardware security module. Where the risk model demands more, use stronger measures.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.