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

# Tools

> Understand how Averta filters OpenAI tools and checks model-requested tool calls.

OpenAI tool protection has two separate stages:

* **Tool exposure**: remove tools before the model sees them.
* **Tool-call check**: evaluate a model-requested tool call before your app executes it.

Do not collapse these in your mental model. Exposure controls planning. Tool-call checks control execution.

## Responses Tools

For Responses API request-time filtering, the wrapper understands:

* function tools, keyed by `name`
* custom tools, keyed by `name`
* hosted OpenAI tools, keyed by `type`
* MCP tools, keyed as `mcp:<server_label>` when `server_label` exists

<CodeGroup>
  ```typescript TypeScript theme={null}
  const tools = [
    {
      type: "function" as const,
      name: "search_docs",
      description: "Search docs.",
      strict: true,
      parameters: {
        type: "object",
        properties: {
          query: { type: "string" },
        },
        required: ["query"],
        additionalProperties: false,
      },
    },
    {
      type: "function" as const,
      name: "send_email",
      description: "Send an email.",
      strict: true,
      parameters: {
        type: "object",
        properties: {
          to: { type: "string" },
          subject: { type: "string" },
          body: { type: "string" },
        },
        required: ["to", "subject", "body"],
        additionalProperties: false,
      },
    },
  ];
  ```

  ```python Python theme={null}
  tools = [
      {
          "type": "function",
          "name": "search_docs",
          "description": "Search docs.",
          "strict": True,
          "parameters": {
              "type": "object",
              "properties": {"query": {"type": "string"}},
              "required": ["query"],
              "additionalProperties": False,
          },
      },
      {
          "type": "function",
          "name": "send_email",
          "description": "Send an email.",
          "strict": True,
          "parameters": {
              "type": "object",
              "properties": {
                  "to": {"type": "string"},
                  "subject": {"type": "string"},
                  "body": {"type": "string"},
              },
              "required": ["to", "subject", "body"],
              "additionalProperties": False,
          },
      },
  ]
  ```
</CodeGroup>

If policy blocks `send_email`, the wrapper forwards only the remaining tools.

## Chat Completions Tools

For Chat Completions, the wrapper understands function and custom tools.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const tools = [
    {
      type: "function" as const,
      function: {
        name: "search_docs",
        description: "Search docs.",
        strict: true,
        parameters: {
          type: "object",
          properties: {
            query: { type: "string" },
          },
          required: ["query"],
          additionalProperties: false,
        },
      },
    },
  ];
  ```

  ```python Python theme={null}
  tools = [
      {
          "type": "function",
          "function": {
              "name": "search_docs",
              "description": "Search docs.",
              "strict": True,
              "parameters": {
                  "type": "object",
                  "properties": {"query": {"type": "string"}},
                  "required": ["query"],
                  "additionalProperties": False,
              },
          },
      }
  ]
  ```
</CodeGroup>

When tools are filtered, the wrapper also sanitizes `tool_choice` so the request does not force a blocked tool.

## Decision Callback

Use `onDecision` to inspect original, blocked, and forwarded tools.

<CodeGroup>
  ```typescript TypeScript theme={null}
  client = wrapOpenAI(client, {
    onDecision(event) {
      if (event.checkpointType !== "request") {
        return;
      }

      console.log("decision:", event.decision.decision);
      console.log("blocked tools:", event.decision.blockedTools ?? []);
      console.log("forwarded tools:", event.forwardedTools.length);
    },
  });
  ```

  ```python Python theme={null}
  def on_decision(event):
      if event["checkpoint_type"] != "request":
          return

      decision = event["decision"]
      print("decision:", decision.decision)
      print("blocked tools:", decision.blocked_tools or [])
      print("forwarded tools:", len(event["forwarded_tools"]))
  ```
</CodeGroup>

## Tool-call Checks

After OpenAI returns a tool call, Averta checks it before guarded tool-call events are exposed to your app.

If the tool-call decision is `block`, the wrapper throws. Your app should not execute the tool.

## Debugging

| Symptom                              | Check                                                                                                   |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------- |
| Tool disappeared                     | Inspect request decision `blockedTools`.                                                                |
| Forced tool choice was ignored       | The requested tool may have been blocked and `tool_choice` sanitized.                                   |
| Tool-call event throws               | The tool-call checkpoint blocked execution.                                                             |
| Hosted tool not filtered as expected | Confirm policy uses the normalized tool identity, such as `web_search_preview` or `mcp:<server_label>`. |
