“Who approved that?”
The approval was a line in a prompt. The model read it, then decided for itself whether it applied.
ConvOps governance puts approval gates in your AI agent workflows. Where your process needs a person, the workflow holds: the engine checks every gate against real state, and the AI cannot move past one that is unmet.
gates checked by the engine · refusals name the reason · every change written down
task Fix checkout timeoutexample
the AI starts the workflow
Ship the timeout fix?
With approval gates the engine checks, rules delivered into the step the agent is on, and an audit row for every change, in the AI client your team already uses.
ConvOps is the operations layer for AI agents: an MCP server that holds your team's process as workflows, with approval gates, a shared memory and an audit trail. It runs no AI models.
updated
Most AI setups govern with wording. The model reads the rule, then decides for itself whether it applies.
“Who approved that?”
The approval was a line in a prompt. The model read it, then decided for itself whether it applied.
“Did anyone check the tests?”
The chat says they passed. Nobody can tell if that is a fact or a sentence the model wrote.
“Which rule was it following?”
Standards live in pasted prompts that drift. Every person runs a slightly different copy.
One fix, asked in Claude. The AI does the work. The engine holds the line. A person decides.
Someone asks Claude to fix the checkout timeout. ConvOps opens a task with the team's bug fix workflow attached, before any code is touched.
The AI receives only the current step: reproduce, then fix. It cannot read ahead or jump to the end.
Reproduce the timeout and note the cause.
Write the smallest fix. Add a regression test as a child task.
not shown yet
not shown yet
The fix is done and the AI asks to advance. The engine checks the gate: no approval yet, tests still running. The cursor stays put.
Tests finish. You read the change and say yes. The next advance carries your OK, the gate is met, and the work moves on.
Ship the checkout timeout fix?
Every change to the task and the workflow was written down as it happened: what changed, the agent's label, and the verified account behind it.
example data
You are the AI. Find a way past the review gate. Then switch sides and approve as the human.
task Fix checkout timeoutexample
Pick a move on the left. The engine answers every advance.
Gates sit only where you put them. Between gates the AI works at full speed.
Changes to tasks and workflows are recorded as they happen: what changed, the agent's label, and the verified account behind it.
What the AI calls itself. Self-declared, so treated as a label.
Stamped by the server from the credential. Never a parameter, so it cannot be typed in.
Tasks and workflow instances. There is no separate approver field.
waiting for the first change
example data · field-level before and after · tasks and workflow instances
Approval, finished tests, a required note. Checked against real state on every advance. Unmet means the cursor does not move.
refuses, with reasons
Policies are written once and delivered inside the step the AI is working on. Guidance it reads, not a lock. Gates are the lock.
edit once, every run
Each change to a task or workflow keeps the agent's self-declared label apart from the verified account it ran under.
tasks + workflows
Owner, admin, member. Checked by the server, with a real refusal when a role is not enough. Nothing more granular.
owner · admin · member
Gate keys sit on the step and are evaluated by the engine on every advance: approval, children finished, task status, a required context note.
{
"id": "approve",
"gate": {
"requires_approval": true,
"wait_for_children": true,
"prompt": "Ship it?"
}
}When a gate is unmet, the cursor does not move and the response lists each unmet condition. Approval is passed explicitly on the advance call, never inferred from chat text.
// the AI asks to advance; the gate is unmet
workflow_advance(task_id="…")
{
"current_step": { "id": "review" },
"unmet_conditions": [
"Requires explicit user approval",
"1 of 1 child tasks are not completed"
]
}A policy is reusable text, global or per workflow, injected into the active step when the agent reads it. Edit it once and every run picks it up. It informs; gates enforce.
{
"slug": "cite-or-cut",
"text": "Every factual claim carries a
source or it does not ship.",
"enabled": true,
"assigned": ["bug-fix", "content-os"]
}Changes to tasks and workflow instances write field-level before and after. The actor field is the agent label the caller declares. The human is stamped by the server from the verified credential. There is no separate approver field.
{
"actor": "implementer",
"actor_user_name": "David Marsa",
"action": "updated",
"entity_type": "task",
"changes": {
"status": { "old": "review", "new": "completed" }
}
}Not by asking or by writing that it was approved. The engine evaluates the gate on every advance against real state, and an unmet gate leaves the cursor where it is, with the unmet conditions listed. Approval has to be passed explicitly on the advance call.
No, and we say so. Policies are rules delivered into the step the agent is working on, so the rule is in front of it at the moment it acts. The enforcement mechanism is the gate. We keep the two apart on purpose.
The advance that passes the gate is written to the audit with the agent's label and the verified account the call ran under. There is no separate approver field, so the record shows the account behind the advance, not a signed approval.
Field-level before and after on tasks and workflow instances, plus a high-level activity feed. It does not claim to cover every table in the product.
The agent label is self-declared, so treat it as a label. The human identity is never a parameter: the server derives it from the verified credential, so there is nowhere in a request to forge it.
Three roles: owner, admin and member, checked at the route and service layer with real refusals, and the last owner cannot be removed. Plain by design.