> ## Documentation Index
> Fetch the complete documentation index at: https://agentstack.beeai.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Approve Tool Calls

> Implement a human-in-the-loop workflow by requiring user authorization before an agent executes specific tools.

Many agent frameworks support the ability to request user approval before executing certain actions. This is especially useful when an agent is calling external tools that may have significant effects or costs associated with their usage.
The **Approval Extension** pauses execution and prompts the user with the tool details, resuming only after approval is granted.

## Basic Implementation

To implement approvals, you inject the extension and call `request_approval()` within your tool execution logic or a framework handler.
This example uses the [BeeAI Framework](https://framework.beeai.dev/modules/agents/requirement-agent#ask-permission-requirement) to request user approval before executing a tool call:

```python theme={null}
# Copyright 2025 © BeeAI a Series of LF Projects, LLC
# SPDX-License-Identifier: Apache-2.0
import os
from typing import Annotated, Any

from a2a.types import Message, TextPart
from agentstack_sdk.a2a.extensions import (
    ApprovalExtensionParams,
    ApprovalExtensionServer,
    ApprovalExtensionSpec,
    ToolCallApprovalRequest,
)
from agentstack_sdk.server import Server
from agentstack_sdk.server.context import RunContext
from beeai_framework.adapters.mcp.serve.server import _tool_factory
from beeai_framework.agents.requirement import RequirementAgent
from beeai_framework.agents.requirement.requirements.ask_permission import AskPermissionRequirement
from beeai_framework.backend import ChatModel
from beeai_framework.tools import AnyTool
from beeai_framework.tools.think import ThinkTool

server = Server()


@server.agent()
async def basic_approve_example(
    input: Message,
    context: RunContext,
    approval_ext: Annotated[ApprovalExtensionServer, ApprovalExtensionSpec(params=ApprovalExtensionParams())],
):
    async def handler(tool: AnyTool, input: dict[str, Any]) -> bool:

        response = await approval_ext.request_approval(
            # using MCP Tool data model as intermediary to simplify conversion
            ToolCallApprovalRequest.from_mcp_tool(_tool_factory(tool), input=input),
            context=context,
        )
        return response.approved

    think_tool = ThinkTool()
    agent = RequirementAgent(
        llm=ChatModel.from_name(os.getenv("LLM_MODEL", "ollama:gpt-oss:20b")),
        tools=[think_tool],
        requirements=[AskPermissionRequirement([think_tool], handler=handler)],
    )

    result = await agent.run("".join(part.root.text for part in input.parts if isinstance(part.root, TextPart)))
    yield result.output[0].text


def run():
    server.run(host=os.getenv("HOST", "127.0.0.1"), port=int(os.getenv("PORT", 8000)))


if __name__ == "__main__":
    run()

```

<Steps>
  <Step title="Import the Approval extension">
    Import `ApprovalExtensionServer`, `ApprovalExtensionSpec`, `ApprovalExtensionParams`, and `ToolCallApprovalRequest` from `agentstack_sdk.a2a.extensions`.
  </Step>

  <Step title="Inject the extension">
    Add an approval parameter to your agent function using the `Annotated` type hint with `ApprovalExtensionServer` and `ApprovalExtensionSpec`.
  </Step>

  <Step title="Request user approval">
    Within your agent logic or tool handler, call await `approval_ext.request_approval()`. This triggers a UI prompt for the user and pauses execution until they respond.
  </Step>

  <Step title="Handle the response">
    Access the approved boolean from the response. If `True`, proceed with the tool execution; if `False`, handle the rejection gracefully (e.g., by yielding a message to the user).
  </Step>
</Steps>
