Operator Approval Flows for AI Agents: A Technical Guide
Operator Approval Flows for AI Agents: A Technical Guide
When an AI agent can take actions inside your product on behalf of a user, someone on your team needs to be able to see exactly what it decided, approve or reject those decisions before they execute, and pull a full conversation trace after the fact. Not because AI is untrustworthy by default — because trust at scale requires an audit trail.
This is what operator approval flows are for. This guide covers how they work, when to use them, and how to implement them in ResolveKit.
What Is an Operator Approval Flow?
An approval flow is a checkpoint in an AI agent's execution where the agent pauses before running a sensitive action and waits for a human to confirm or deny it. The operator — your support engineer, your on-call developer, your trust and safety team — sees the proposed action, the context that led to it, and can approve, reject, or ask for more information.
Approval flows sit at the intersection of two concerns:
- **Agent capability** — the AI can handle more cases autonomously because it knows a human is watching
- **Operator control** — your team has full visibility and authority over what the agent does
Without this, you either give the AI full autonomy (risky for sensitive actions) or you hard-code every decision (defeats the purpose of having an AI agent). Approval flows let you thread that needle.
Why Approval Flows Matter
Three concrete reasons:
1. Regulatory and compliance requirements
If your product handles payments, medical data, legal documents, or any PII, you likely have audit log requirements. Approval flows generate the records you need: who approved what, when, and why.
2. Catching model hallucinations before they cause damage
LLMs hallucinate. They also misinterpret user intent. A well-designed approval flow catches a refund request that should have been a billing dispute, or a password reset addressed to the wrong email, before it becomes a support ticket — or worse.
3. Tuning AI behavior over time
When operators consistently reject certain categories of agent decisions, that signal feeds back into your system prompt, your tool definitions, or your fine-tuning data. Approval flows are a learning loop, not just a safety gate.
The Three States of an Approval Flow
ResolveKit models every tool function with one of three execution policies:
Auto-approved — the function runs without operator involvement. Use for low-risk, reversible actions: fetching account metadata, checking order status, looking up a tracking number.
Requires approval — the function pauses and surfaces to the operator dashboard. The agent waits. Nothing executes until a human says yes or no.
Blocked — the function cannot be called by the agent under any circumstances. Use this to hard-disable certain capabilities (like account deletion or password changes) regardless of what the LLM requests.
@ResolveKit(
name: "reset_password",
description: "Send a password reset email to the user",
timeout: 10,
requiresApproval: true // pauses, surfaces to operator dashboard
)
struct ResetPassword: ResolveKitFunction {
func perform(userId: String) async throws -> Bool {
// your implementation
return true
}
}@ResolveKit(
name: "delete_account",
description: "Permanently delete a user account and all associated data",
timeout: 30,
requiresApproval: false, // auto-approved? no — this is blocked at the policy level
policy: .blocked // hard-disabled regardless
)
struct DeleteAccount: ResolveKitFunction {
func perform(userId: String) async throws -> Bool {
// your implementation
return true
}
}The Operator Dashboard
When a function with `requiresApproval: true` is triggered, the event appears in the ResolveKit operator dashboard in real time. The operator sees:
- **The conversation context** — full chat history leading up to the tool call
- **The proposed action** — which function, with which arguments
- **The user's request** — what the user was trying to do
- **The AI's reasoning** — the LLM's chain-of-thought explanation for why it chose this action
The operator can then:
- **Approve** — the function executes, the user gets their result
- **Reject** — the agent is told the action was denied and asked to try a different approach
- **Modify and approve** — change the arguments (e.g., correct a user ID) before approving
- **Request more info** — send the agent a message to gather additional context
Every action is logged with operator ID, timestamp, and the reasoning behind the decision. This is your audit trail.
Configuring Policies at Scale
Individual `@ResolveKit` annotations work at the function level, but ResolveKit also supports policy-level configuration that applies across all functions or scopes them by context.
You can set policies by:
- **App version** — more conservative policies for older builds
- **User role** — higher-privilege users get fewer approval gates (e.g., internal test accounts)
- **Function category** — group functions by risk level and apply consistent policies
- **Traffic volume** — throttle approval-required functions during peak load
This means you don't have to annotate every function individually. You define the rules once, and the SDK enforces them at runtime.
let policy = ApprovalPolicy(
default: .autoApprove,
overrides: [
.functionCategory(.financial): .requiresApproval,
.functionCategory(.accountManagement): .requiresApproval,
.appVersion("..<1.2.0"): .blocked,
.userRole(.admin): .autoApprove,
]
)Trace Logs: The Full Story
Approval decisions are only half the picture. ResolveKit maintains a full conversation trace for every session — not just what the agent said, but what it decided, what it attempted to do, and what the operator did about it.
A trace record includes:
- Timestamps for every message, tool call, approval decision, and function result
- The exact arguments passed to each function
- Whether the operator approved, rejected, or modified the call
- Any follow-up actions the agent took after the decision
You can query traces via the ResolveKit API to build your own reporting, feed them into a SIEM, or use them to generate compliance reports on demand.
SDK Integration
ResolveKit's approval flow system is built into the SDK at the runtime level. The operator dashboard is a separate web interface — no additional SDK configuration is needed to connect the two. You configure functions and policies in your app code; the backend handles routing to the dashboard and enforcing the decisions.
import ResolveKitUI
let runtime = ResolveKitRuntime(configuration: ResolveKitConfiguration(
apiKeyProvider: { "rk_your_api_key" },
functions: [
GetLocalTime.self, // auto-approved
SendMessage.self, // requiresApproval
ResetPassword.self, // requiresApproval
DeleteAccount.self, // blocked at policy level
]
))The SDK handles the waiting state — if the operator hasn't responded within the configured timeout, the agent can either fail gracefully or escalate to a human, depending on your policy settings.
When to Use Each Policy
| Action type | Policy | Reason |
|---|---|---|
| Read-only data lookups | Auto-approve | Low risk, no side effects |
| Sending messages / notifications | Auto-approve or requires approval | Depends on recipient scope |
| Password resets, email changes | Requires approval | Account takeover risk |
| Payments, refunds, subscriptions | Requires approval | Financial and legal exposure |
| Account deletion, data export | Blocked or requires approval | Data destruction risk |
| Admin actions, role changes | Requires approval | Privilege escalation risk |
Get Started
Operator approval flows are available today in the ResolveKit iOS and Android SDKs. The operator dashboard is included in both the self-hosted and managed tiers.
- [Operator Approval Flows documentation](https://docs.resolvekit.app) — full SDK reference
- [iOS SDK on GitHub](https://github.com/resolve-kit/resolvekit-ios-sdk) — source and sample app
- [Android SDK on GitHub](https://github.com/resolve-kit/resolvekit-android-sdk) — the Android equivalent
To set up your backend: Start Free — no credit card required, managed tier starts at $0.50 per resolved conversation.