How pending approvals work for agents
When an agent calls a scope flagged require_approval, the platform call doesn’t happen immediately — it queues, you decide, and the result lands back at the agent.
This article is for understanding what the agent should do during the “waiting” window so the human talking to it gets a sensible experience.
The receipt
The agent’s use_platform call returns a receipt instead of the platform’s response:
{
"status": "pending_approval",
"approval_id": "uuid",
"expires_at": "...",
"created_at": "..."
}The AgentValet MCP server has special handling for this — it doesn’t return the receipt to the LLM as if it were a normal response. Instead, it waits (up to ~50 seconds) for the approval to land, then either:
- Returns the actual platform response (if you approved within that window)
- Returns the
pending_approvalenvelope with a clear next-action message (if you didn’t)
What the agent should say
If the MCP server returns the pending_approval envelope, the LLM should tell the user something like:
“That’s queued for your approval. I’ll check back, or you can approve it now at app.agentvalet.ai/approvals.”
Not:
“Done.” (it isn’t)
Not:
“Failed.” (it isn’t)
Polling under the hood
For curiosity rather than usual use — the agent’s MCP server polls GET /v1/approvals/:id while waiting. Returns:
{
"status": "pending" | "approved" | "denied" | "expired",
"result": { ... }, // only when approved + executed
"execution_error": "...", // only on failure during re-execution
"expires_at": "...",
"executed_at": "..."
}Rate-limited to 60 polls per minute per agent. The MCP server back-offs are tuned for the 50-second blocking window — don’t write your own polling loop on top of this unless you’re building a non-Claude integration.
Catching up later
If the user comes back after the 50-second window and asks “did the Stripe thing go through?”, the agent can call list_my_pending_actions. That returns:
- Currently-pending approvals for this agent
- Recently-completed approvals from the last 24 hours, including the platform response or denial
Use this to give the user a status without re-issuing the original action (which would queue another approval).
When approvals expire
The queue row defaults to a 10-minute TTL. After that, status is expired and the agent gets a clear denial on its next poll. The agent should tell the user the action wasn’t approved in time and offer to try again.
Next
- How approval works (conceptual)
- Approve in the dashboard
- Configure permissions — to change which scopes require approval