# Configure tool authorization (/en/docs/developers/agent/embed/tool-authorization)





Choose whether enabled tools run immediately or ask the user to confirm. This guide uses an orders MCP server with query and return tools. Your tool server must still enforce business permissions.

## Prepare the tools [#prepare]

Start with a working service agent. Connect an MCP server named `orders` under **配置 → MCP 与凭据** (Configuration → MCP and credentials). The example requires enabled `list_orders` and `request_return` tools. Replace these names with your actual server and tools; do not configure nonexistent example tools.

A confirmation card is not authentication. A public MCP service must authenticate the platform caller before applying end-user data restrictions. See [Secure tool access](/en/docs/developers/agent/embed/security#tool-access).

## Choose an execution policy [#policies]

| Policy         | Effect on ordinary enabled tools                                   |
| -------------- | ------------------------------------------------------------------ |
| `always_allow` | Executes without asking                                            |
| `always_ask`   | Pauses for confirmation; allow executes the call, deny prevents it |

These are the two supported policies. Do not use `auto`: even where a type accepts it, the runtime rejects execution. Disable a tool to prevent its use entirely. Asking still lets the user approve a call.

Policies do not bypass mandatory tool interactions, security boundaries, or business checks. Client `custom` tools execute in your page and do not use these confirmation policies.

## Configure tools and defaults [#configure]

<Tabs items="['Dashboard', 'API']">
  <Tab value="Dashboard">
    In the current Dashboard, open **服务智能体 → your agent → 接入与配置 → 配置 → 工具与授权** (Service agents → your agent → Integration and configuration → Configuration → Tools and authorization).

    1. Under **授权方式**, set **orders · 默认授权** to **每次询问** (Ask every time).
    2. Set `list_orders` to **自动执行** (Run automatically) and `request_return` to **每次询问**. Individual selectors only appear for configured tools. Other tools inherit the default; use the API to add individual settings if needed.
    3. Save. &#x2A;*Expected:** the configuration version increases. Existing sessions retain their original version.
  </Tab>

  <Tab value="API">
    Replace `agent_example`, save this as `authorize-tools.ts`, and run `bun authorize-tools.ts` on your backend with `PRAXIS_API_KEY` set. The script preserves other tools and settings, modifying only orders authorization. The `version` field detects concurrent changes.

    ```ts
    // authorize-tools.ts — run on the server with: bun authorize-tools.ts
    const key = process.env.PRAXIS_API_KEY;
    if (!key) throw new Error("Set PRAXIS_API_KEY on the server");
    const url = "https://api-develop.deepraxis.com/agent/v1/agents/agent_example";
    const headers = { Authorization: `Bearer ${key}`, "Content-Type": "application/json" };
    const read = await fetch(url, { headers });
    if (!read.ok) throw new Error(`Read failed: ${read.status}`);
    const current = await read.json();
    const tools = current.tools ?? [];
    const orders = tools.find((tool: { type: string; mcp_server_name?: string }) =>
      tool.type === "mcp_toolset" && tool.mcp_server_name === "orders");
    if (!orders) throw new Error("Connect the orders MCP server first");
    orders.default_config = {
      ...orders.default_config,
      permission_policy: { type: "always_ask" },
    };
    orders.configs = orders.configs ?? [];
    for (const [name, type] of [
      ["list_orders", "always_allow"],
      ["request_return", "always_ask"],
    ]) {
      const existing = orders.configs.find((item: { name: string }) => item.name === name);
      if (existing) existing.permission_policy = { type };
      else orders.configs.push({ name, permission_policy: { type } });
    }
    const response = await fetch(url, {
      method: "POST", headers,
      body: JSON.stringify({ version: current.version, tools }),
    });
    if (!response.ok) throw new Error(`Update failed: ${response.status}`);
    const saved = await response.json();
    console.log({ id: saved.id, version: saved.version });
    ```

    **Expected:** HTTP 200 and a new version printed in the terminal. The script stops on a failed read or update. Resolve the error and read the version again before retrying; do not blindly resend stale configuration.
  </Tab>
</Tabs>

Resolution follows individual `configs[].permission_policy`, then `default_config.permission_policy`, then the tool default. Without an explicit MCP policy, only `annotations.readOnlyHint === true` defaults to allow. Otherwise, it defaults to ask. This server hint affects only the default; explicit settings take priority.

The built-in toolset defaults to `always_allow` when no default policy is specified, while mandatory tool interactions still apply. Explicitly require confirmation for refunds, deletion, and external messages instead of relying on server hints.

## Verify confirmation [#verify]

Issue an embed token for the new version and create a new session. If your policy pins a version, update that pin or specify the new version during issuance. Saving an agent does not upgrade existing sessions.

Request an order lookup, then a test return. &#x2A;*Expected:** the lookup runs immediately; the return shows a Kit confirmation card. Denying must prevent the server-side action. Request it again and allow it to proceed. Verify actual execution in your tool server's records rather than relying only on the model's answer.

Kit supplies the confirmation UI. An embedded user's approval applies to that call and does not save permanent tool permissions. For complete scenarios, see [Test your integration](/en/docs/developers/agent/embed/testing).

## Next steps [#next]

[Protect tool access](/en/docs/developers/agent/embed/security#tool-access) · [Client tools](/en/docs/developers/agent/embed/client-tools) · [Update agent API](/en/docs/api/native/agent/updateAgent).
