# AgentOps Control Center – Human Approval for Agentic AI

> Built a control plane for agentic AI in accounts payable, using backend policy, a human approval gate and a transactional action ledger, so that an approved action runs exactly once and every step is audited.

- Author: Daniil Hirchyts
- Published: November 7, 2026
- URL: https://hirchyts-daniil.me/projects/agentops-control-center
- Link: https://github.com/Daniil-Hirchyts/AgentOps-Control-Center

Companies want AI agents that do work, and an agent that does work can also do damage. It can pay the wrong invoice, act on an instruction hidden in a document, or repeat an action after a timeout. So the pilot stalls when someone in risk or finance asks who answers for the action once the agent can take one.

AgentOps Control Center is a working answer to that question, built by a team of two during my Master of Engineering (MEng) in Big Data & Machine Learning at Efrei Paris. It is a web application that sits between an AI agent and the business action it wants to take. **The agent can analyze and recommend. Only a named person can release the action, and it runs exactly once.** Every step is recorded for audit.

## One Invoice, From Start to Finish

We built it around a realistic accounts-payable case. The invoice data is synthetic and the model is real (Qwen 3.5 9B, running locally).

1. **Alice, an operator, files a case.** Northwind Logistics has billed €48,750 for freight. Its typical invoice is €4,200.
2. **The agent analyzes it.** The model reads the invoice, compares it with the vendor's history and proposes one action: flag the invoice for review.
3. **The run stops.** Nothing has happened yet in the business system. Bob, the reviewer, gets a notification on his phone.
4. **Bob decides.** He sees the same evidence the agent saw, and approves or rejects from any device.
5. **The system acts and records.** On approval the action runs once. The ledger and audit trail show who decided what, when and on which evidence.

The demo below plays that sequence, then shows what happens when it goes wrong.

## Where the Control Lives

The principle is that **the model recommends and the backend decides**. Four mechanisms enforce it, none of which depends on the model behaving well.

| The risk | The control | Enforced by |
| --- | --- | --- |
| The model invents or is talked into an action | A fixed allowlist of two actions, flag or do nothing | A Rust enum compiled into the service |
| The model waves its own proposal through | The backend ignores the model's opinion on approval | Backend policy |
| The model returns garbage or the provider fails | At most two attempts, then a failed run with nothing executed | The run state machine |
| A double click, retry or crash repeats the action | One ledger row per approval, written in the same transaction as the business change | A unique constraint in PostgreSQL |

Invoice text is untrusted input that goes straight to the LLM, so we treat prompt injection as a certainty. The defense does not try to detect it. Whatever the injected text persuades the model to say, the backend can only do what is on the list, and only after a person agrees.

Concurrency gets the same treatment. Every status change is a conditional update, so when two people act at once, one succeeds and the other receives a clean conflict. Interrupted runs are recovered at startup. Finance teams get the guarantee without any distributed locking to operate.

![AgentOps demo at 4× speed: the operator files an invoice on a laptop, the agent analyses it, the reviewer is notified on a phone and approves, while a live diagram shows the backend traffic](https://hirchyts-daniil.me/projects/agentops/agentops-demo.mp4)

## What an Auditor Sees

Each model request and response, status change, decision and action is an audit event with its actor, displayed as a timeline on the run. "The AI did it" becomes a named reviewer, a timestamp and the exact evidence shown at the moment of the decision.

![An agent run stopped at the approval gate: the 48,750 EUR invoice at 11.6 times its typical amount, the proposed action, the waiting reviewer and the audit activity](https://hirchyts-daniil.me/projects/agentops/agentops.jpg)

## Built to Be Deployed

The integration surface is intentionally small. One HTTP client speaks to any OpenAI-compatible endpoint, so a client can stay on a private model or a hosted one under its own data agreements. The stack ships as one Rust service, PostgreSQL and a React front end under Docker Compose, with the API description generated from the code and checked in CI.

A deterministic mock keeps the tests independent of a GPU or an API key: 29 backend tests, 22 of them against a real PostgreSQL, 55 frontend tests and 3 end-to-end scenarios driving two browsers at once.

## Where It Applies Next

The invoice is the first workflow. Adding a process means adding its actions to the allowlist and its rules to the policy.

| Function | The agent proposes | A person approves |
| --- | --- | --- |
| Procurement | Hold on a purchase order | Category manager |
| Insurance | Settlement of a claim | Claims handler |
| Customer care | Refund above a limit | Team lead |
| IT operations | Configuration change | Change manager |

The rollout follows the same pattern in each case: start inside one process, keep every action gated while trust is earned, and use the audit trail to show which low-risk actions can later run without review.

The limits are worth stating. An injected instruction can still talk the model into recommending no action, and the run then closes without a flag. The gate stops unauthorized actions; it cannot stop a missed detection. A production rollout would pair the model with deterministic rules on amount and vendor history, and send a sample of closed runs to human quality control. The system is also an MVP: one workflow and two roles on a single instance, not yet used by a real finance team. Identity-provider integration, thresholds by amount and an ERP connection come next.
