Approval Workflows for AI Agents
As AI agents gain the ability to take real-world actions — sending emails, modifying databases, calling external APIs, spending money — organizations need a way to keep humans in the loop for high-stakes decisions. Govyn's approval workflow system intercepts agent requests that match configurable rules and holds them for human review before they reach the LLM provider or downstream service.
This is not observability. Observability tells you what happened after the fact. Approval workflows prevent things from happening until a human says they should. The agent's request is physically held at the proxy layer. It does not reach the provider, does not trigger side effects, and does not cost money until an approver makes a decision.
The system is fully asynchronous. The agent sends a request, receives a polling URL, and waits. The approver reviews the request in the dashboard or through a webhook notification and approves or denies it. The proxy then forwards the approved request or returns a denial to the agent. The agent does not need to know about the approval system — it handles the async response like any other retry or wait pattern.
Why AI agents need approval gates
AI agents are increasingly autonomous. They compose emails, write code, query databases, call APIs, and make purchasing decisions. Most of the time, their actions are correct and beneficial. But the failure modes are severe: a misaddressed email, an incorrect database migration, a spend that exceeds the budget by an order of magnitude, or a data access that violates compliance requirements.
The challenge is that these high-risk actions are often indistinguishable from routine actions at the code level. An agent calling a "send email" function is the same code path whether the email goes to a colleague or to every customer in the database. A database write that updates one row uses the same API as one that drops a table. Without a governance layer that understands the difference, you are relying on the agent's judgment to know when to stop — and that judgment is only as good as the prompt and the model.
Approval gates address this by defining explicit boundaries. You specify which actions require human sign-off, and the proxy enforces those boundaries at the network layer. The agent cannot bypass the gate because it never has direct access to the downstream service. Every request must pass through the proxy, and the proxy will not forward requests that match an approval rule until a human approves them.
This architecture is particularly important for regulated industries — finance, healthcare, legal, government — where autonomous AI actions may need documented human oversight. Approval workflows provide the paper trail: who approved what, when, and why. This is not a feature you add later; it is a requirement you build in from the start.
How the approval system works
The approval system is built into the Govyn proxy. When a request arrives, the proxy evaluates it against all active policies in priority order. If a policy with approval_required: true matches the request, the proxy initiates the approval flow instead of forwarding the request to the provider.
The proxy generates a unique approval token with the gva_ prefix — 32 random bytes encoded as base64url. This token identifies the specific request in the approval queue and serves as the authentication mechanism for status polling. The proxy creates an approval item in the database with the full request details, the matching policy, the agent identity, and the timestamp.
The proxy returns a structured JSON response to the agent containing the approval token and a polling URL. The response follows the standard Govyn error contract with type, message, policy, and agent fields, plus a poll_url field specific to approval responses. The agent (or its framework) polls this URL to check whether the request has been approved, denied, or is still pending.
The polling endpoint at GET /api/v1/approvals/:token/status is publicly accessible — it does not require organization-level authentication because the token itself is the credential. This design allows the proxy to poll without needing Clerk JWT tokens, which simplifies the async flow. The token is unguessable (256 bits of entropy), making brute-force access infeasible.
When an approver makes a decision, the approval item's status is updated in the database. The next time the agent polls, it receives the decision. If approved, the proxy forwards the original request to the provider and returns the response to the agent. If denied, the proxy returns a denial response with the approver's optional note.
Common approval scenarios
Approval rules are most valuable when applied to actions with real-world consequences that are difficult or impossible to undo. Here are the scenarios where teams most commonly deploy approval gates:
- External communications — any agent action that sends an email, posts a Slack message, creates a support ticket, or communicates with external parties. A misaddressed or poorly worded message sent autonomously can damage customer relationships, violate communication policies, or disclose confidential information.
- Database mutations — INSERT, UPDATE, and DELETE operations against production databases. A single incorrect WHERE clause can affect thousands of rows. Approval gates let a human verify the query scope before it executes.
- High-cost operations — LLM requests that exceed a token threshold. An agent requesting a 100,000-token completion on GPT-4 costs significantly more than a typical request. Approval ensures that expensive operations are intentional.
- External API calls with side effects — calling payment processors, deploying infrastructure, modifying DNS records, or any API where the action changes state in an external system. These actions often cannot be rolled back.
- Sensitive data access — queries against tables containing PII, financial records, health data, or other regulated information. Approval gates provide documented authorization for each access, satisfying audit requirements.
- Code deployment and infrastructure changes — agents that have access to CI/CD pipelines or infrastructure-as-code tools. Requiring approval before an agent can trigger a deployment or modify infrastructure prevents autonomous changes to production systems.
- Content publication — agents that draft and publish blog posts, social media updates, documentation, or other public-facing content. Approval ensures a human reviews the content before it goes live.
The common thread is irreversibility. Approval gates are most valuable for actions where the cost of an error is high and the ability to undo the action is limited or nonexistent.
Configuring approval rules
Approval rules are defined as policies in YAML or through the dashboard policy editor. A policy with approval_required: true will intercept matching requests and route them to the approval queue. Here are examples of common configurations:
Require approval for all requests from a specific agent:
policies:
- name: approve-deployment-agent
type: approval
priority: 10
approval_required: true
conditions:
agent: deployment-bot
message: "Deployment agent requests require human approval" Require approval for requests exceeding a token threshold:
policies:
- name: approve-large-requests
type: approval
priority: 20
approval_required: true
conditions:
max_tokens_threshold: 50000
message: "Requests over 50k tokens require approval" Require approval for requests to premium models:
policies:
- name: approve-premium-models
type: approval
priority: 15
approval_required: true
conditions:
models:
- gpt-4
- gpt-4-turbo
- claude-3-opus
message: "Premium model usage requires approval" Require approval for requests matching content patterns:
policies:
- name: approve-email-sends
type: approval
priority: 5
approval_required: true
conditions:
content_patterns:
- "send.*email"
- "send.*message"
- "post.*slack"
message: "External communication requires approval"
Policies are evaluated in ascending priority order — lower numbers are evaluated first. When multiple policies match a request, the first matching policy with approval_required: true takes effect. This lets you create broad approval rules with specific exceptions by adjusting priority levels.
The approval lifecycle
Every approval request follows the same lifecycle from interception to resolution. Understanding each step helps you design effective approval policies and troubleshoot issues.
- Request interception — the agent sends an LLM request to the Govyn proxy. The proxy evaluates the request against all active policies in priority order. A policy with
approval_required: truematches the request. - Queue creation — the proxy generates a
gva_approval token, stores the full request payload and metadata in the approval queue, and records which policy triggered the approval requirement. - Response to agent — the proxy returns a structured JSON response to the agent with the approval token and a polling URL. The HTTP status code indicates that the request is pending, not failed.
- Notification dispatch — if webhook alert rules are configured for approval events, the proxy sends POST requests to the configured webhook URLs with the pending approval details. This is how approvers learn that something needs their attention.
- Agent polling — the agent (or its framework) polls the status endpoint at
GET /api/v1/approvals/:token/status. The endpoint returns the current status: pending, approved, or denied. Polling is lightweight — the endpoint reads a single row by primary key. - Human review — an approver opens the approval queue in the dashboard, reviews the request details including the agent name, the request payload, the matching policy, and the timestamp. The approver decides whether the request should proceed.
- Decision with note — the approver clicks Approve or Deny and optionally adds a note explaining their reasoning. The note is stored with the decision as part of the permanent audit trail.
- Resolution — the approval item's status is updated in the database. On the next poll, the agent receives the decision. If approved, the proxy forwards the original request to the LLM provider and returns the response to the agent. If denied, the proxy returns a denial response.
The entire lifecycle is recorded in the database. Every state transition is timestamped. The full request payload, the decision, the approver identity, and the note are all stored and queryable through the API and the dashboard history tab.
Approval notifications
The approval system integrates with Govyn's alert and notification infrastructure. When a new item enters the approval queue, the system checks for alert rules configured for approval events and dispatches webhook notifications to the configured endpoints.
Webhook notifications contain the full approval item details: the agent name, the request summary, the policy that triggered the approval, the approval token, and a direct link to the dashboard approval queue. This gives approvers enough context to make a decision without needing to open the dashboard first.
Common notification destinations include:
- Slack — send approval notifications to a dedicated channel. The webhook payload can be formatted as a Slack Block Kit message with approve/deny buttons (requires a Slack app that proxies the action back to the Govyn API).
- Email — route notifications through an email service like SendGrid or SES. Include the request summary and a link to the dashboard.
- PagerDuty — create incidents for time-sensitive approvals that need immediate attention.
- Custom endpoints — any HTTP service that accepts POST requests. Build custom approval notification flows for your organization's tooling.
Webhook URLs are validated against SSRF protections. Private IP ranges (RFC 1918), localhost addresses, and cloud metadata endpoints are blocked to prevent server-side request forgery attacks through the notification system. The notification history in the dashboard shows delivery status for every webhook dispatch, including success/failure indicators and response codes.
Dashboard approval queue
The approval queue in the Govyn Cloud Dashboard is the primary interface for managing approval requests. It has two tabs: Pending and History.
The Pending tab shows all approval items awaiting a decision. Each item displays the agent name, a summary of the request, the policy that triggered the approval requirement, and the time elapsed since the request was queued. The tab polls every 5 seconds for new items, so approvers see requests within seconds of them being queued. Items are ordered by creation time, with the oldest pending items at the top.
Clicking a pending item opens a detail drawer with the full request payload. The approver can review the exact content of the agent's request — the model, the messages, the parameters — and understand what the agent is trying to do. Two action buttons at the bottom of the drawer — Approve and Deny — each accept an optional note. The note field is a free-text input where the approver explains their reasoning. Notes like "Verified recipient list is correct" or "Denied: budget for this project is exhausted" become part of the permanent record.
The History tab shows every past approval decision. Each entry includes the original request, the decision (approved, denied, or timed out), the approver's identity, any notes, and the exact timestamps for when the request was queued and when the decision was made. History is paginated with cursor-based pagination and can be filtered by status. This tab serves as the compliance log — it answers the questions auditors ask: who authorized this action, when, and why.
The approval queue is organization-scoped. Approvers can only see and act on items from their own organization. Cross-organization access is prevented at both the API and database layers. The approve and deny endpoints verify that the approval item belongs to the authenticated user's organization before processing the action.
Audit trail
Every approval decision creates a permanent, immutable audit record. The audit trail captures:
- Who requested — the agent identity (from the
X-Govyn-Agentheader) and the session identifier (from theX-Govyn-Sessionheader) that originated the request. - What was requested — the full request payload, including the model, messages, and parameters. For requests to downstream APIs, the target URL and request body.
- Why it was flagged — the specific policy name and configuration that triggered the approval requirement.
- Who decided — the Clerk user identity of the approver who made the decision. This links to the organization's user directory for accountability.
- What they decided — approved or denied, with the exact timestamp of the decision.
- Why they decided — the optional note provided by the approver. This is the human-readable explanation of the reasoning.
- How long it took — the time elapsed between the request being queued and the decision being made. This metric helps organizations optimize their approval response times.
Audit data is stored in PostgreSQL via Prisma and is subject to your plan's log retention limits: 7 days on Starter, 30 days on Team, and 90 days on Enterprise. Full request and response payloads are stored in Cloudflare R2 object storage with the R2 key referenced in the database record. This separation keeps the database lean while preserving complete payloads for replay and investigation.
The audit trail is queryable through the API at GET /api/v1/approvals/history?limit=&cursor=. Organizations that need longer retention or integration with external compliance systems can export this data through the API before it ages out of the retention window.
Timeout and auto-deny
Not every approval request will receive a timely human response. Approvers may be unavailable, notifications may be missed, or the approval may arrive outside business hours. The timeout system ensures that unanswered requests do not hang indefinitely.
When an approval request is not acted on within the configured timeout period, the system automatically denies it. The approval item's status is updated to "timed out" (a variant of denial), and the next time the agent polls the status endpoint, it receives a denial response indicating that the request was not approved within the allowed window.
The timeout behavior is important for agent reliability. Without timeouts, an agent waiting for approval could block its entire execution pipeline indefinitely. With timeouts, agents can handle the denial gracefully — falling back to a safer action, retrying with a smaller request, or notifying a human through a different channel.
Timed-out items appear in the approval history with a distinct status. This lets you identify patterns — if a particular type of request is consistently timing out, you may need to adjust your notification routing, extend the timeout window, or reconsider whether approval is necessary for that action type.
For organizations that need 24/7 approval coverage, combining webhook notifications with an on-call rotation ensures that approval requests always reach a human within the timeout window. The PagerDuty integration is designed for this use case — it creates an incident for each pending approval and escalates through your on-call schedule.
Frequently asked questions
What are approval workflows in Govyn?
How does the approval flow work technically?
gva_ token, creates a queue item, and returns a polling URL to the agent. The agent polls the status endpoint asynchronously. A human reviews the request in the dashboard or via webhook notification and approves or denies it. The proxy then forwards the request if approved or returns a denial response.
What actions can require approval?
Can I add notes when approving or denying?
How are approvers notified?
What happens if nobody responds in time?
Is there an audit trail?
Can different agents have different approval rules?
What plans support approval workflows?
Does the agent need code changes?
Enable approval workflows on Team plan
Add human-in-the-loop governance to your AI agents. Define approval rules in minutes and start reviewing requests from the dashboard.
Get started See pricing