eve/ The Agent Framework Workshop

Human Approval

Let the agent inspect Supabase without interruption, but pause before it performs a database mutation.

Add approval to the Supabase connection

The Supabase MCP server publishes both read-only and mutation-capable tools. Add a policy to the existing connection so eve asks for approval only when the model selects an operation that can change data or infrastructure.

Update agent/connections/supabase.ts, keeping the connector UID that eve add generated for you:

import { connect } from "@vercel/connect/eve";
import { defineMcpClientConnection } from "eve/connections";
 
const MUTATING_TOOL_PATTERN =
  /__(execute_sql|apply_migration|create_|update_|delete_|deploy_|pause_|restore_|merge_|reset_|rebase_)/i;
 
export default defineMcpClientConnection({
  url: "https://mcp.supabase.com/mcp",
  description:
    "Supabase: databases, authentication, and storage. Mutation-capable operations are gated by eve human approval before execution.",
  auth: connect("mcp.supabase.com/<your-connector-name>"),
  approval: ({ toolName }) =>
    MUTATING_TOOL_PATTERN.test(toolName)
      ? "user-approval"
      : "not-applicable",
});

The policy receives a qualified tool name such as supabase__execute_sql. Read-only discovery operations continue without an approval prompt; matching operations park the run before the MCP request reaches Supabase.

This workshop uses a conservative approval policy. For your own agent, decide what requires human approval based on your risk tolerance and the consequences of an incorrect call.

Add approval rules to instructions

The approval policy runs outside the model and is not automatically included in an MCP tool's description. Update agent/instructions.md so the agent knows it may request protected operations and that eve will pause before they run:

- The Supabase MCP connection is configured to require human approval for
  mutation-capable operations, including `execute_sql` and `apply_migration`.
  You may request these tools when the user explicitly asks for a mutation;
  eve will pause before execution.
- Use read-only Supabase discovery tools to identify the project and schema
  before requesting a mutation. If more than one project matches, ask the user
  to choose.

The runtime policy remains the enforcement layer. These instructions give the model accurate context so it requests the gated tool instead of incorrectly refusing the task.

Test the approval flow

Request a gated Supabase mutation, deny it once, then approve it. Eve pauses the turn while you decide and resumes the same session after you respond.

  1. Restart local development.

    npm run dev
  2. Request a ticket update.

    Prompt
    Use read-only Supabase tools to find the project whose public schema contains the tickets table. Then request an update to ticket TKT-1042: set its status to investigating and its internal note to "Account facts collected; escalating to identity team." Do not modify any other record.

    Watch for connection_search followed by a qualified Supabase MCP tool such as supabase__execute_sql. The policy parks the run before Supabase receives the mutation.

  3. Deny the first request.

    Review the tool name and arguments, then choose Deny. Open the tickets table in Supabase and confirm that TKT-1042 is still open.

  4. Repeat and approve.

    Send the same prompt again. Confirm that the proposed SQL targets only TKT-1042 with the expected status and note, then choose Approve.

  5. Verify the database result.

    Refresh the tickets table. The approved request should change TKT-1042 to investigating and preserve every other row.

  6. Deploy the updated agent.

    npx eve deploy

    Slack uses the production deployment, so publish the new connection policy and instructions before testing the approval there. Wait for the deployment to finish successfully.

  7. Try the same flow in Slack.

    Prompt
    Use read-only Supabase tools to find the project whose public schema contains the tickets table. Then request an update to ticket TKT-1042: keep its status as investigating and set its internal note to "Slack update: still investigating." Do not modify any other record.

    The Slack channel renders the pending approval as native interactive controls. The durable session can wait without holding compute, then resumes when someone answers.

What happens under the hood

1

Model requests a mutation

The model discovers the Supabase connection and selects a mutation-capable MCP tool, such as supabase__execute_sql.

2

Policy requires approval

The connection policy returns user-approval before the MCP request runs.

3

Session parks

eve emits input.requested, enters session.waiting, and checkpoints the turn durably.

4

Human responds

A terminal, Slack, or web client submits Approve or Deny.

Approve

Resumes the same turn and sends the request to Supabase.

Deny

Prevents the MCP call. No database change runs.

The approval gate protects every matching call, including one replayed after an interruption. Production mutations should still use database constraints or transactions appropriate to their side effects.

Pause to ask clarifying questions

The built-in ask_question tool uses the same durable pause-and-resume protocol as approval. You do not need to define it. Instructions such as “ask for the account ID when it is missing” tell the model to wait for an answer instead of inventing one.

You are ready when

Congratulations, you built an agent! You now have an agent that uses tools, connects to Supabase, runs in Slack, and pauses sensitive actions for human approval.

What next?