---
title: Llamada programática de herramientas
url: https://platform.claude.com/docs/es/agents-and-tools/tool-use/programmatic-tool-calling
description: Permite que Claude llame a tus herramientas desde código en el contenedor de ejecución de código, reduciendo los viajes de ida y vuelta al modelo y el uso de tokens en flujos de trabajo con múltiples herramientas.
featureMetadata:
  status: ga
  zdr: not-eligible
  supportedModels:
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-fable-5
    - claude-mythos-5
    - claude-opus-5-5
    - claude-opus-5
    - claude-opus-4-8
    - claude-opus-4-7
    - claude-opus-4-6
    - claude-opus-4-5-20251101
    - claude-sonnet-5-5
    - claude-sonnet-5
    - claude-sonnet-4-6
    - claude-sonnet-4-5-20250929
    - claude-haiku-5-5
  supportedPlatforms:
    Claude API: ga
    Claude Platform on AWS: ga
    Microsoft Foundry:
      availability: ga
      note: En [Microsoft Foundry](https://platform.claude.com/docs/es/build-with-claude/claude-in-microsoft-foundry), la llamada programática de herramientas requiere una [implementación alojada en Anthropic](https://platform.claude.com/docs/es/build-with-claude/claude-in-microsoft-foundry#additional-features-not-supported-when-hosted-on-azure).
  details:
    - La llamada programática de herramientas requiere la herramienta de ejecución de código con la [versión de herramienta](https://platform.claude.com/docs/es/agents-and-tools/tool-use/code-execution-tool#tool-versions) `code_execution_20260120` o posterior.
    - Claude Haiku 4.5 acepta las versiones de herramienta `code_execution_20260120` y posteriores, pero no admite la llamada programática de herramientas.
---

La "programmatic tool calling" (llamada programática de herramientas) permite que Claude escriba código que llama a tus herramientas de forma programática dentro de un contenedor de [ejecución de código](https://platform.claude.com/docs/es/agents-and-tools/tool-use/code-execution-tool), en lugar de requerir viajes de ida y vuelta a través del modelo para cada invocación de herramienta. Esto reduce la "latency" (latencia) en flujos de trabajo con múltiples herramientas y disminuye el consumo de tokens al permitir que Claude filtre o procese los datos antes de que lleguen a la "context window" (ventana de contexto) del modelo. En benchmarks de búsqueda agéntica como [BrowseComp](https://arxiv.org/abs/2504.12516) y [DeepSearchQA](https://github.com/google-deepmind/deepsearchqa), que evalúan la investigación web de múltiples pasos y la recuperación de información compleja, agregar la llamada programática de herramientas sobre las herramientas de búsqueda básicas mejoró el rendimiento en un promedio del 11% mientras usaba un 24% menos de tokens de entrada (consulta [Improved web search with dynamic filtering](https://claude.com/blog/improved-web-search-with-dynamic-filtering)).

Considera verificar el cumplimiento del presupuesto de 20 empleados: el enfoque tradicional requiere 20 viajes de ida y vuelta al modelo por separado, incorporando miles de partidas de gastos al contexto en el camino. Con la llamada programática de herramientas, un solo script ejecuta las 20 consultas, filtra los resultados y devuelve solo los empleados que excedieron sus límites, reduciendo lo que Claude necesita razonar de cientos de kilobytes a unas pocas líneas.

<Tip>
  Para un análisis más profundo de los costos de inferencia y de contexto que aborda la llamada programática de herramientas, consulta [Advanced tool use](https://www.anthropic.com/engineering/advanced-tool-use).
</Tip>

La llamada programática de herramientas requiere la [herramienta de ejecución de código](https://platform.claude.com/docs/es/agents-and-tools/tool-use/code-execution-tool) con la versión de herramienta `code_execution_20260120` o posterior. Para comprobar si un modelo admite la llamada programática de herramientas antes de enviar una solicitud, lee su valor `capabilities.code_execution.supported` desde la Models API. [Uso de la API de Models](https://platform.claude.com/docs/es/models/overview#using-the-models-api) describe el campo.

## Inicio rápido

Aquí hay un ejemplo en el que Claude consulta una base de datos de forma programática varias veces y agrega los resultados. Agregar `allowed_callers: ["code_execution_20260120"]` a una definición de herramienta es lo que hace que esa herramienta se pueda llamar desde dentro de la ejecución de código (consulta [El campo `allowed_callers`](https://platform.claude.com/docs/es/agents-and-tools/tool-use/programmatic-tool-calling#the-allowed-callers-field)):

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
      --header "x-api-key: $ANTHROPIC_API_KEY" \
      --header "anthropic-version: 2023-06-01" \
      --header "content-type: application/json" \
      --data '{
          "model": "claude-opus-5-5",
          "max_tokens": 4096,
          "messages": [
              {
                  "role": "user",
                  "content": "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue"
              }
          ],
          "tools": [
              {
                  "type": "code_execution_20260120",
                  "name": "code_execution"
              },
              {
                  "name": "query_database",
                  "description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
                  "input_schema": {
                      "type": "object",
                      "properties": {
                          "sql": {
                              "type": "string",
                              "description": "SQL query to execute"
                          }
                      },
                      "required": ["sql"]
                  },
                  "allowed_callers": ["code_execution_20260120"]
              }
          ]
      }'
  ```

  ```bash CLI
  ant messages create <<'YAML'
  model: claude-opus-5-5
  max_tokens: 4096
  messages:
    - role: user
      content: >-
        Query sales data for the West, East, and Central regions, then
        tell me which region had the highest revenue
  tools:
    - type: code_execution_20260120
      name: code_execution
    - name: query_database
      description: >-
        Execute a SQL query against the sales database. Returns a list
        of rows as JSON objects.
      input_schema:
        type: object
        properties:
          sql:
            type: string
            description: SQL query to execute
        required:
          - sql
      allowed_callers:
        - code_execution_20260120
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=4096,
      messages=[
          {
              "role": "user",
              "content": "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue",
          }
      ],
      tools=[
          {"type": "code_execution_20260120", "name": "code_execution"},
          {
              "name": "query_database",
              "description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "sql": {"type": "string", "description": "SQL query to execute"}
                  },
                  "required": ["sql"],
              },
              "allowed_callers": ["code_execution_20260120"],
          },
      ],
  )

  print(response)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 4096,
    messages: [
      {
        role: "user",
        content:
          "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue"
      }
    ],
    tools: [
      {
        type: "code_execution_20260120",
        name: "code_execution"
      },
      {
        name: "query_database",
        description:
          "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
        input_schema: {
          type: "object" as const,
          properties: {
            sql: {
              type: "string",
              description: "SQL query to execute"
            }
          },
          required: ["sql"]
        },
        allowed_callers: ["code_execution_20260120"]
      }
    ]
  });

  console.log(response);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 4096,
      Messages = [
          new() {
              Role = Role.User,
              Content = "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue"
          }
      ],
      Tools = [
          new CodeExecutionTool20260120(),
          new ToolUnion(new Tool()
          {
              Name = "query_database",
              Description = "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
              InputSchema = new InputSchema()
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["sql"] = JsonSerializer.SerializeToElement(new { type = "string", description = "SQL query to execute" }),
                  },
                  Required = ["sql"],
              },
              AllowedCallers = ["code_execution_20260120"]
          }),
      ]
  };

  var message = await client.Messages.Create(parameters);
  Console.WriteLine(message);
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 4096,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue")),
  	},
  	Tools: []anthropic.ToolUnionParam{
  		{OfCodeExecutionTool20260120: &anthropic.CodeExecutionTool20260120Param{}},
  		{OfTool: &anthropic.ToolParam{
  			Name:        "query_database",
  			Description: anthropic.String("Execute a SQL query against the sales database. Returns a list of rows as JSON objects."),
  			InputSchema: anthropic.ToolInputSchemaParam{
  				Properties: map[string]any{
  					"sql": map[string]any{
  						"type":        "string",
  						"description": "SQL query to execute",
  					},
  				},
  				Required: []string{"sql"},
  			},
  			AllowedCallers: []string{"code_execution_20260120"},
  		}},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  fmt.Println(response.RawJSON())
  ```

  ```java Java
  import com.anthropic.models.messages.CodeExecutionTool20260120;
  // ...

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(4096L)
          .addUserMessage("Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue")
          .addTool(CodeExecutionTool20260120.builder().build())
          .addTool(Tool.builder()
              .name("query_database")
              .description("Execute a SQL query against the sales database. Returns a list of rows as JSON objects.")
              .inputSchema(InputSchema.builder()
                  .properties(JsonValue.from(Map.of(
                      "sql", Map.of(
                          "type", "string",
                          "description", "SQL query to execute"
                      )
                  )))
                  .putAdditionalProperty("required", JsonValue.from(List.of("sql")))
                  .build())
              .allowedCallers(List.of(Tool.AllowedCaller.of("code_execution_20260120")))
              .build())
          .build();

      Message response = client.messages().create(params);
      IO.println(response);
  }
  ```

  ```php PHP
  $client = new Client();

  $message = $client->messages->create(
      maxTokens: 4096,
      messages: [
          ['role' => 'user', 'content' => 'Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue'],
      ],
      model: 'claude-opus-5-5',
      tools: [
          [
              'type' => 'code_execution_20260120',
              'name' => 'code_execution',
          ],
          [
              'name' => 'query_database',
              'description' => 'Execute a SQL query against the sales database. Returns a list of rows as JSON objects.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'sql' => [
                          'type' => 'string',
                          'description' => 'SQL query to execute',
                      ],
                  ],
                  'required' => ['sql'],
              ],
              'allowed_callers' => ['code_execution_20260120'],
          ],
      ],
  );

  echo $message;
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  message = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 4096,
    messages: [
      {
        role: "user",
        content: "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue"
      }
    ],
    tools: [
      {
        type: "code_execution_20260120",
        name: "code_execution"
      },
      {
        name: "query_database",
        description: "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
        input_schema: {
          type: "object",
          properties: {
            sql: {
              type: "string",
              description: "SQL query to execute"
            }
          },
          required: ["sql"]
        },
        allowed_callers: ["code_execution_20260120"]
      }
    ]
  )

  puts message
  ```
</CodeGroup>

La respuesta se detiene con `stop_reason: "tool_use"`, un ID de `container` y un bloque `tool_use` para `query_database` cuyo campo `caller` identifica la ejecución de código que lo llamó. Devuelve el resultado como se muestra en el [Paso 3 del flujo de trabajo de ejemplo](https://platform.claude.com/docs/es/agents-and-tools/tool-use/programmatic-tool-calling#step-3-provide-tool-result) para que el código pueda finalizar.

## Cómo funciona la llamada programática de herramientas

Cuando configuras una herramienta para que se pueda llamar desde la ejecución de código y Claude determina que esa herramienta es necesaria:

1. Claude escribe código Python que invoca la herramienta como una función, incluyendo potencialmente múltiples llamadas a herramientas y lógica de pre/posprocesamiento
2. Claude ejecuta este código en un contenedor aislado (sandbox) mediante la ejecución de código
3. Cuando se llama a una función de herramienta, la ejecución de código se pausa y la API devuelve un bloque `tool_use`
4. Proporcionas el resultado de la herramienta y la ejecución de código continúa (los resultados intermedios no se cargan en la ventana de contexto de Claude)
5. Una vez que toda la ejecución de código finaliza, Claude recibe la salida final y continúa trabajando en la tarea

Este enfoque es particularmente útil para:

* **Procesamiento de grandes volúmenes de datos:** Filtra o agrega los resultados de las herramientas antes de que lleguen al contexto de Claude
* **Flujos de trabajo de múltiples pasos:** Ahorra tokens y latencia llamando a las herramientas en serie o en un bucle sin muestrear a Claude entre las llamadas a herramientas
* **Lógica condicional:** Toma decisiones basadas en resultados intermedios de las herramientas

<Note>
  Las herramientas que permiten un llamador de ejecución de código se exponen al código de Claude como funciones asíncronas de Python, por lo que Claude puede ejecutarlas en paralelo con `asyncio.gather`. Cada función recibe un único dict de argumentos y devuelve una cadena: el texto del `tool_result` que envías de vuelta. El código de Claude espera estas funciones con `await` de nivel superior y analiza los resultados que necesita como datos estructurados, por ejemplo `rows = json.loads(await query_database({"sql": "<sql>"}))`.
</Note>

## Conceptos fundamentales

### El campo `allowed_callers`

El campo `allowed_callers` especifica qué contextos pueden invocar una herramienta:

```json
{
  "name": "query_database",
  "description": "Execute a SQL query against the database",
  "input_schema": {
    // ...
  },
  "allowed_callers": ["code_execution_20260120"]
}
```

**Valores posibles:**

* `["direct"]` - Se guía a Claude para que llame a esta herramienta directamente (valor predeterminado si se omite)
* `["code_execution_20260120"]` - Se guía a Claude para que llame a esta herramienta solo desde dentro de la ejecución de código
* `["direct", "code_execution_20260120"]` - Claude puede llamar a esta herramienta directamente o desde dentro de la ejecución de código

Tanto `"code_execution_20260120"` como `"code_execution_20260521"` se aceptan en `allowed_callers` y son intercambiables: una solicitud que use cualquiera de las dos versiones de la herramienta de ejecución de código satisface a las herramientas que listan cualquiera de los dos llamadores. Los bloques de respuesta siempre etiquetan al llamador como `code_execution_20260120` independientemente de la versión que haya declarado la solicitud.

<Tip>
  Elige `["direct"]` o `["code_execution_20260120"]` para cada herramienta en lugar de habilitar ambos, ya que esto proporciona una guía más clara a Claude sobre cómo usar mejor la herramienta.
</Tip>

<Note>
  `allowed_callers` controla cómo se presenta la herramienta a Claude y se valida contra `tool_choice`, pero no es un bloqueo estricto a nivel de API sobre la invocación directa. Se guía firmemente a Claude para que lo respete, pero tu cliente aún debe estar preparado para manejar un `tool_use` directo para cualquier herramienta que defina. No dependas de `allowed_callers` como una barrera de seguridad.
</Note>

### El campo `caller` en las respuestas

Cada bloque de uso de herramientas incluye un campo `caller` que indica cómo fue invocado:

**Invocación directa (uso de herramientas tradicional):**

```json
{
  "type": "tool_use",
  "id": "toolu_abc123",
  "name": "query_database",
  "input": { "sql": "<sql>" },
  "caller": { "type": "direct" }
}
```

**Invocación programática:**

```json
{
  "type": "tool_use",
  "id": "toolu_xyz789",
  "name": "query_database",
  "input": { "sql": "<sql>" },
  "caller": {
    "type": "code_execution_20260120",
    "tool_id": "srvtoolu_abc123"
  }
}
```

El `tool_id` es el `id` del bloque `server_tool_use` de ejecución de código que realizó la llamada, por lo que puedes asociar cada `tool_use` programático con la ejecución de código que lo produjo.

### Ciclo de vida del contenedor

La llamada programática de herramientas usa los mismos contenedores que la ejecución de código:

* **Creación del contenedor:** Se crea un nuevo contenedor para cada solicitud a menos que reutilices uno existente
* **ID del contenedor:** Se devuelve en las respuestas en el campo `container`, junto con una marca de tiempo `expires_at`
* **Reutilización:** Pasa el ID del contenedor de vuelta en la siguiente solicitud para mantener el estado. Mientras una llamada programática de herramienta está esperando tu resultado, el ID del contenedor es obligatorio en esa solicitud, no opcional: la API rechaza la solicitud sin él.
* **Expiración:** `expires_at` te indica cuánto tiempo le queda al contenedor. Actualmente, los contenedores inactivos se recuperan después de unos 5 minutos, y ningún contenedor puede reutilizarse más de 30 días después de su creación.

<Warning>
  Mientras el código de Claude está esperando un resultado de herramienta programático, la llamada pendiente agota su tiempo de espera después de unos 4 minutos y lanza un `TimeoutError` dentro del código. Devuelve cada resultado de herramienta mucho antes de la marca de tiempo `expires_at` de la respuesta pausada. Consulta [Expiración del contenedor durante la llamada a la herramienta](https://platform.claude.com/docs/es/agents-and-tools/tool-use/programmatic-tool-calling#container-expiration-during-tool-call).
</Warning>

## Flujo de trabajo de ejemplo

Así es como funciona un flujo completo de llamada programática de herramientas:

### Paso 1: Solicitud inicial

Envía una solicitud con ejecución de código y una herramienta que permita la llamada programática. Para habilitar la llamada programática, agrega el campo `allowed_callers` a la definición de tu herramienta.

<Note>
  Proporciona descripciones detalladas del formato de salida de tu herramienta en la descripción de la herramienta. Si especificas que la herramienta devuelve JSON, Claude intenta deserializar y procesar el resultado en código. Cuantos más detalles proporciones sobre el esquema de salida, mejor podrá Claude manejar la respuesta de forma programática.
</Note>

La forma de la solicitud es idéntica al ejemplo de [Inicio rápido](https://platform.claude.com/docs/es/agents-and-tools/tool-use/programmatic-tool-calling#quick-start): incluye `code_execution` en tu lista de herramientas, agrega `allowed_callers: ["code_execution_20260120"]` a cualquier herramienta que quieras que Claude invoque desde código, y envía tu mensaje de usuario. Los pasos restantes de este flujo de trabajo usan el mensaje de usuario `"Query customer purchase history from the last quarter and identify our top 5 customers by revenue"`.

### Paso 2: Respuesta de la API con llamada a herramienta

Claude escribe código que llama a tu herramienta. La API se pausa y devuelve:

```json Output
{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "I'll query the purchase history and analyze the results."
    },
    {
      "type": "server_tool_use",
      "id": "srvtoolu_abc123",
      "name": "code_execution",
      "input": {
        "code": "import json\n\nrows = json.loads(await query_database({'sql': '<sql>'}))\ntop_customers = sorted(rows, key=lambda x: x['revenue'], reverse=True)[:5]\nprint(f'Top 5 customers: {top_customers}')"
      }
    },
    {
      "type": "tool_use",
      "id": "toolu_def456",
      "name": "query_database",
      "input": { "sql": "<sql>" },
      "caller": {
        "type": "code_execution_20260120",
        "tool_id": "srvtoolu_abc123"
      }
    }
  ],
  "container": {
    "id": "container_xyz789",
    "expires_at": "2026-01-20T14:30:00Z"
  },
  "stop_reason": "tool_use"
}
```

### Paso 3: Proporcionar el resultado de la herramienta

Envía el historial completo de la conversación más el resultado de tu herramienta. Tres detalles importan en esta solicitud:

* El mensaje de usuario que lleva tu resultado solo puede contener bloques `tool_result`. Consulta [Restricciones de formato de mensajes](https://platform.claude.com/docs/es/agents-and-tools/tool-use/programmatic-tool-calling#message-formatting-restrictions).
* Pasa el ID de `container` de la respuesta pausada. La API rechaza una continuación que tenga llamadas programáticas de herramientas pendientes pero ningún ID de contenedor.
* Envía el mismo arreglo `tools` que en la solicitud original. La herramienta de ejecución de código debe seguir presente para que el código pausado se reanude, y las herramientas que envíes en esta solicitud son las definiciones que Claude y el código en ejecución pueden usar durante el resto del turno.

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
      --header "x-api-key: $ANTHROPIC_API_KEY" \
      --header "anthropic-version: 2023-06-01" \
      --header "content-type: application/json" \
      --data '{
          "model": "claude-opus-5-5",
          "max_tokens": 4096,
          "container": "container_xyz789",
          "messages": [
              {
                  "role": "user",
                  "content": "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"
              },
              {
                  "role": "assistant",
                  "content": [
                      {
                          "type": "text",
                          "text": "I'\''ll query the purchase history and analyze the results."
                      },
                      {
                          "type": "server_tool_use",
                          "id": "srvtoolu_abc123",
                          "name": "code_execution",
                          "input": {"code": "..."}
                      },
                      {
                          "type": "tool_use",
                          "id": "toolu_def456",
                          "name": "query_database",
                          "input": {"sql": "<sql>"},
                          "caller": {
                              "type": "code_execution_20260120",
                              "tool_id": "srvtoolu_abc123"
                          }
                      }
                  ]
              },
              {
                  "role": "user",
                  "content": [
                      {
                          "type": "tool_result",
                          "tool_use_id": "toolu_def456",
                          "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}, {\"customer_id\": \"C2\", \"revenue\": 38000}]"
                      }
                  ]
              }
          ],
          "tools": [
              {
                  "type": "code_execution_20260120",
                  "name": "code_execution"
              },
              {
                  "name": "query_database",
                  "description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
                  "input_schema": {
                      "type": "object",
                      "properties": {
                          "sql": {
                              "type": "string",
                              "description": "SQL query to execute"
                          }
                      },
                      "required": ["sql"]
                  },
                  "allowed_callers": ["code_execution_20260120"]
              }
          ]
      }'
  ```

  ```bash CLI
  ant messages create <<'YAML'
  model: claude-opus-5-5
  max_tokens: 4096
  container: container_xyz789
  messages:
    - role: user
      content: >-
        Query customer purchase history from the last quarter and identify our
        top 5 customers by revenue
    - role: assistant
      content:
        - type: text
          text: I'll query the purchase history and analyze the results.
        - type: server_tool_use
          id: srvtoolu_abc123
          name: code_execution
          input:
            code: "..."
        - type: tool_use
          id: toolu_def456
          name: query_database
          input:
            sql: "<sql>"
          caller:
            type: code_execution_20260120
            tool_id: srvtoolu_abc123
    - role: user
      content:
        - type: tool_result
          tool_use_id: toolu_def456
          content: >-
            [{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2",
            "revenue": 38000}, ...]
  # El mismo array de herramientas que en la solicitud original
  tools:
    - type: code_execution_20260120
      name: code_execution
    - name: query_database
      description: >-
        Execute a SQL query against the sales database. Returns a list
        of rows as JSON objects.
      input_schema:
        type: object
        properties:
          sql:
            type: string
            description: SQL query to execute
        required:
          - sql
      allowed_callers:
        - code_execution_20260120
  YAML
  ```

  ```python Python
  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=4096,
      container="container_xyz789",  # Reuse the container
      messages=[
          {
              "role": "user",
              "content": "Query customer purchase history from the last quarter and identify our top 5 customers by revenue",
          },
          {
              "role": "assistant",
              "content": [
                  {
                      "type": "text",
                      "text": "I'll query the purchase history and analyze the results.",
                  },
                  {
                      "type": "server_tool_use",
                      "id": "srvtoolu_abc123",
                      "name": "code_execution",
                      "input": {"code": "..."},
                  },
                  {
                      "type": "tool_use",
                      "id": "toolu_def456",
                      "name": "query_database",
                      "input": {"sql": "<sql>"},
                      "caller": {
                          "type": "code_execution_20260120",
                          "tool_id": "srvtoolu_abc123",
                      },
                  },
              ],
          },
          {
              "role": "user",
              "content": [
                  {
                      "type": "tool_result",
                      "tool_use_id": "toolu_def456",
                      "content": '[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]',
                  }
              ],
          },
      ],
      # El mismo array de herramientas que en la solicitud original
      tools=[
          {"type": "code_execution_20260120", "name": "code_execution"},
          {
              "name": "query_database",
              "description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "sql": {"type": "string", "description": "SQL query to execute"}
                  },
                  "required": ["sql"],
              },
              "allowed_callers": ["code_execution_20260120"],
          },
      ],
  )

  print(response)
  ```

  ```typescript TypeScript
  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 4096,
    container: "container_xyz789", // Reuse the container
    messages: [
      {
        role: "user",
        content:
          "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"
      },
      {
        role: "assistant",
        content: [
          { type: "text", text: "I'll query the purchase history and analyze the results." },
          {
            type: "server_tool_use",
            id: "srvtoolu_abc123",
            name: "code_execution",
            input: { code: "..." }
          },
          {
            type: "tool_use",
            id: "toolu_def456",
            name: "query_database",
            input: { sql: "<sql>" },
            caller: {
              type: "code_execution_20260120",
              tool_id: "srvtoolu_abc123"
            }
          }
        ]
      },
      {
        role: "user",
        content: [
          {
            type: "tool_result",
            tool_use_id: "toolu_def456",
            content:
              '[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]'
          }
        ]
      }
    ],
    // El mismo arreglo de herramientas que en la solicitud original
    tools: [
      {
        type: "code_execution_20260120",
        name: "code_execution"
      },
      {
        name: "query_database",
        description:
          "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
        input_schema: {
          type: "object" as const,
          properties: {
            sql: {
              type: "string",
              description: "SQL query to execute"
            }
          },
          required: ["sql"]
        },
        allowed_callers: ["code_execution_20260120"]
      }
    ]
  });

  console.log(response);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 4096,
      Container = "container_xyz789",
      Messages =
      [
          new()
          {
              Role = Role.User,
              Content = "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"
          },
          new()
          {
              Role = Role.Assistant,
              Content = new ContentBlock[]
              {
                  new TextBlock { Text = "I'll query the purchase history and analyze the results." },
                  new ServerToolUseBlock
                  {
                      Id = "srvtoolu_abc123",
                      Name = "code_execution",
                      Input = new { code = "..." }
                  },
                  new ToolUseBlock
                  {
                      Id = "toolu_def456",
                      Name = "query_database",
                      Input = new { sql = "<sql>" },
                      Caller = new ToolCaller
                      {
                          Type = "code_execution_20260120",
                          ToolId = "srvtoolu_abc123"
                      }
                  }
              }
          },
          new()
          {
              Role = Role.User,
              Content = new ContentBlockParam[]
              {
                  new ToolResultBlockParam
                  {
                      ToolUseID = "toolu_def456",
                      Content = "[{\"customer_id\": \"C1\", \"revenue\": 45000}, {\"customer_id\": \"C2\", \"revenue\": 38000}, ...]"
                  }
              }
          }
      ],
      // El mismo arreglo de herramientas que en la solicitud original
      Tools = [
          new CodeExecutionTool20260120(),
          new ToolUnion(new Tool()
          {
              Name = "query_database",
              Description = "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
              InputSchema = new InputSchema()
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["sql"] = JsonSerializer.SerializeToElement(new { type = "string", description = "SQL query to execute" }),
                  },
                  Required = ["sql"],
              },
              AllowedCallers = ["code_execution_20260120"]
          }),
      ]
  };

  var message = await client.Messages.Create(parameters);
  Console.WriteLine(message);
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 4096,
  	Container: anthropic.MessageCreateParamsContainerUnion{
  		OfString: anthropic.String("container_xyz789"),
  	},
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Query customer purchase history from the last quarter and identify our top 5 customers by revenue")),
  		{
  			Role: anthropic.MessageParamRoleAssistant,
  			Content: []anthropic.ContentBlockParamUnion{
  				anthropic.NewTextBlock("I'll query the purchase history and analyze the results."),
  				{OfServerToolUse: &anthropic.ServerToolUseBlockParam{
  					ID:    "srvtoolu_abc123",
  					Name:  anthropic.ServerToolUseBlockParamNameCodeExecution,
  					Input: map[string]any{"code": "..."},
  				}},
  				{OfToolUse: &anthropic.ToolUseBlockParam{
  					ID:    "toolu_def456",
  					Name:  "query_database",
  					Input: map[string]any{"sql": "<sql>"},
  					Caller: anthropic.ServerToolUseBlockParamCallerUnion{
  						OfCodeExecution20260120: &anthropic.ServerToolCaller20260120Param{
  							ToolID: "srvtoolu_abc123",
  						},
  					},
  				}},
  			},
  		},
  		{
  			Role: anthropic.MessageParamRoleUser,
  			Content: []anthropic.ContentBlockParamUnion{
  				{OfToolResult: &anthropic.ToolResultBlockParam{
  					ToolUseID: "toolu_def456",
  					Content: []anthropic.ToolResultBlockParamContentUnion{
  						{OfText: &anthropic.TextBlockParam{
  							Text: `[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]`,
  						}},
  					},
  				}},
  			},
  		},
  	},
  	// El mismo array de herramientas que en la solicitud original
  	Tools: []anthropic.ToolUnionParam{
  		{OfCodeExecutionTool20260120: &anthropic.CodeExecutionTool20260120Param{}},
  		{OfTool: &anthropic.ToolParam{
  			Name:        "query_database",
  			Description: anthropic.String("Execute a SQL query against the sales database. Returns a list of rows as JSON objects."),
  			InputSchema: anthropic.ToolInputSchemaParam{
  				Properties: map[string]any{
  					"sql": map[string]any{
  						"type":        "string",
  						"description": "SQL query to execute",
  					},
  				},
  				Required: []string{"sql"},
  			},
  			AllowedCallers: []string{"code_execution_20260120"},
  		}},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  fmt.Println(response.RawJSON())
  ```

  ```java Java
  import com.anthropic.models.messages.CodeExecutionTool20260120;
  // ...

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(4096L)
          .container("container_xyz789")
          .addUserMessage("Query customer purchase history from the last quarter and identify our top 5 customers by revenue")
          .addAssistantMessageOfBlockParams(List.of(
              ContentBlockParam.ofText(
                  TextBlockParam.builder()
                      .text("I'll query the purchase history and analyze the results.")
                      .build()),
              ContentBlockParam.ofServerToolUse(
                  ServerToolUseBlockParam.builder()
                      .id("srvtoolu_abc123")
                      .name("code_execution")
                      .input(JsonValue.from(Map.of("code", "...")))
                      .build()),
              ContentBlockParam.ofToolUse(
                  ToolUseBlockParam.builder()
                      .id("toolu_def456")
                      .name("query_database")
                      .input(JsonValue.from(Map.of("sql", "<sql>")))
                      .codeExecution20260120Caller("srvtoolu_abc123")
                      .build())
          ))
          .addUserMessageOfBlockParams(List.of(
              ContentBlockParam.ofToolResult(
                  ToolResultBlockParam.builder()
                      .toolUseId("toolu_def456")
                      .content("[{\"customer_id\": \"C1\", \"revenue\": 45000}, {\"customer_id\": \"C2\", \"revenue\": 38000}, ...]")
                      .build())
          ))
          // El mismo array de herramientas que en la solicitud original
          .addTool(CodeExecutionTool20260120.builder().build())
          .addTool(Tool.builder()
              .name("query_database")
              .description("Execute a SQL query against the sales database. Returns a list of rows as JSON objects.")
              .inputSchema(InputSchema.builder()
                  .properties(JsonValue.from(Map.of(
                      "sql", Map.of(
                          "type", "string",
                          "description", "SQL query to execute"
                      )
                  )))
                  .putAdditionalProperty("required", JsonValue.from(List.of("sql")))
                  .build())
              .allowedCallers(List.of(Tool.AllowedCaller.of("code_execution_20260120")))
              .build())
          .build();

      Message response = client.messages().create(params);
      IO.println(response);
  }
  ```

  ```php PHP
  $client = new Client();

  $message = $client->messages->create(
      maxTokens: 4096,
      messages: [
          [
              'role' => 'user',
              'content' => 'Query customer purchase history from the last quarter and identify our top 5 customers by revenue',
          ],
          [
              'role' => 'assistant',
              'content' => [
                  [
                      'type' => 'text',
                      'text' => "I'll query the purchase history and analyze the results.",
                  ],
                  [
                      'type' => 'server_tool_use',
                      'id' => 'srvtoolu_abc123',
                      'name' => 'code_execution',
                      'input' => ['code' => '...'],
                  ],
                  [
                      'type' => 'tool_use',
                      'id' => 'toolu_def456',
                      'name' => 'query_database',
                      'input' => ['sql' => '<sql>'],
                      'caller' => [
                          'type' => 'code_execution_20260120',
                          'tool_id' => 'srvtoolu_abc123',
                      ],
                  ],
              ],
          ],
          [
              'role' => 'user',
              'content' => [
                  [
                      'type' => 'tool_result',
                      'tool_use_id' => 'toolu_def456',
                      'content' => '[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]',
                  ],
              ],
          ],
      ],
      model: 'claude-opus-5-5',
      container: 'container_xyz789',
      // El mismo array de herramientas que en la solicitud original
      tools: [
          [
              'type' => 'code_execution_20260120',
              'name' => 'code_execution',
          ],
          [
              'name' => 'query_database',
              'description' => 'Execute a SQL query against the sales database. Returns a list of rows as JSON objects.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'sql' => [
                          'type' => 'string',
                          'description' => 'SQL query to execute',
                      ],
                  ],
                  'required' => ['sql'],
              ],
              'allowed_callers' => ['code_execution_20260120'],
          ],
      ],
  );

  echo $message;
  ```

  ```ruby Ruby
  require "anthropic"

  client = Anthropic::Client.new

  message = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 4096,
    container: "container_xyz789",
    messages: [
      {
        role: "user",
        content: "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"
      },
      {
        role: "assistant",
        content: [
          {
            type: "text",
            text: "I'll query the purchase history and analyze the results."
          },
          {
            type: "server_tool_use",
            id: "srvtoolu_abc123",
            name: "code_execution",
            input: { code: "..." }
          },
          {
            type: "tool_use",
            id: "toolu_def456",
            name: "query_database",
            input: { sql: "<sql>" },
            caller: {
              type: "code_execution_20260120",
              tool_id: "srvtoolu_abc123"
            }
          }
        ]
      },
      {
        role: "user",
        content: [
          {
            type: "tool_result",
            tool_use_id: "toolu_def456",
            content: '[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]'
          }
        ]
      }
    ],
    # El mismo array de herramientas que en la solicitud original
    tools: [
      {
        type: "code_execution_20260120",
        name: "code_execution"
      },
      {
        name: "query_database",
        description: "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
        input_schema: {
          type: "object",
          properties: {
            sql: {
              type: "string",
              description: "SQL query to execute"
            }
          },
          required: ["sql"]
        },
        allowed_callers: ["code_execution_20260120"]
      }
    ]
  )

  puts message
  ```
</CodeGroup>

### Paso 4: Siguiente llamada a herramienta o finalización

El código retoma donde se pausó y procesa tu resultado. Cada respuesta de continuación o bien se pausa de nuevo con más bloques `tool_use` programáticos, o bien completa la ejecución de código y permite que Claude continúe el turno (Paso 5). Revisa `stop_reason` y el `caller` de cada bloque `tool_use` para distinguir ambos casos: una respuesta que se pausa para ti tiene `stop_reason: "tool_use"` y un bloque `tool_use` cuyo `caller` nombra una versión de ejecución de código, y repites el Paso 3 con un `tool_result` para cada llamada programática pendiente en un solo mensaje de usuario.

### Paso 5: Respuesta final

Una vez que la ejecución de código finaliza, Claude proporciona la respuesta final:

```json Output
{
  "content": [
    {
      "type": "code_execution_tool_result",
      "tool_use_id": "srvtoolu_abc123",
      "content": {
        "type": "code_execution_result",
        "stdout": "Top 5 customers: [{'customer_id': 'C1', 'revenue': 45000}, {'customer_id': 'C2', 'revenue': 38000}, {'customer_id': 'C5', 'revenue': 32000}, {'customer_id': 'C8', 'revenue': 28500}, {'customer_id': 'C3', 'revenue': 24000}]",
        "stderr": "",
        "return_code": 0,
        "content": []
      }
    },
    {
      "type": "text",
      "text": "I've analyzed the purchase history from last quarter. Your top 5 customers generated $167,500 in total revenue, with Customer C1 leading at $45,000."
    }
  ],
  "stop_reason": "end_turn"
}
```

## Patrones avanzados

### Procesamiento por lotes con bucles

Claude puede escribir código que procese múltiples elementos de forma eficiente:

```python
regions = ["West", "East", "Central", "North", "South"]
results = {}
for region in regions:
    rows = json.loads(await query_database({"sql": f"<sql for {region}>"}))
    results[region] = sum(row["revenue"] for row in rows)

# Procesa los resultados de forma programática
top_region = max(results.items(), key=lambda x: x[1])
print(f"Top region: {top_region[0]} with ${top_region[1]:,} in revenue")
```

Este patrón:

* Reduce los viajes de ida y vuelta al modelo de N (uno por región) a 1
* Procesa grandes conjuntos de resultados de forma programática antes de volver a Claude
* Ahorra tokens al devolver solo conclusiones agregadas en lugar de datos sin procesar

### Terminación anticipada

Claude puede dejar de procesar tan pronto como se cumplan los criterios de éxito:

```python
endpoints = ["us-east", "eu-west", "apac"]
for endpoint in endpoints:
    status = await check_health({"endpoint": endpoint})
    if status == "healthy":
        print(f"Found healthy endpoint: {endpoint}")
        break  # Stop early, don't check remaining
```

### Selección condicional de herramientas

```python
path = "/tmp/example.txt"
file_info = json.loads(await get_file_info({"path": path}))
if file_info["size"] < 10000:
    content = await read_full_file({"path": path})
else:
    content = await read_file_summary({"path": path})
print(content)
```

### Filtrado de datos

```python
server_id = "srv-01"
log_text = await fetch_logs({"server_id": server_id})
errors = [line for line in log_text.splitlines() if "ERROR" in line]
print(f"Found {len(errors)} errors")
for error in errors[-10:]:  # Only return last 10 errors
    print(error)
```

## Formato de respuesta

### Llamada programática de herramienta

Cuando la ejecución de código llama a una herramienta:

```json
{
  "type": "tool_use",
  "id": "toolu_abc123",
  "name": "query_database",
  "input": { "sql": "<sql>" },
  "caller": {
    "type": "code_execution_20260120",
    "tool_id": "srvtoolu_xyz789"
  }
}
```

### Manejo del resultado de la herramienta

El resultado de tu herramienta se pasa de vuelta al código en ejecución:

```json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_abc123",
      "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000, \"orders\": 23}, {\"customer_id\": \"C2\", \"revenue\": 38000, \"orders\": 18}, ...]"
    }
  ]
}
```

### Finalización de la ejecución de código

Cuando todas las llamadas a herramientas se han satisfecho y el código finaliza:

```json
{
  "type": "code_execution_tool_result",
  "tool_use_id": "srvtoolu_xyz789",
  "content": {
    "type": "code_execution_result",
    "stdout": "Analysis complete. Top 5 customers identified from 847 total records.",
    "stderr": "",
    "return_code": 0,
    "content": []
  }
}
```

## Manejo de errores

### Errores comunes

| Error                                      | Dónde aparece                                                                   | Descripción                                                                       | Solución                                                                                                                                                  |
| ------------------------------------------ | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid_tool_input`                       | `error_code` en el bloque de error `code_execution_tool_result` de la respuesta | Se pasaron parámetros no válidos a la herramienta de ejecución de código          | Consulta los [errores de la herramienta de ejecución de código](https://platform.claude.com/docs/es/agents-and-tools/tool-use/code-execution-tool#errors) |
| `invalid_request_error` (en `tool_choice`) | Respuesta de error HTTP 400                                                     | `tool_choice` nombra una herramienta cuyo `allowed_callers` no incluye `"direct"` | Agrega `"direct"` al `allowed_callers` de esa herramienta, o elimina la herramienta de `tool_choice` y deja que Claude la invoque desde código            |

### Expiración del contenedor durante la llamada a la herramienta

Si el resultado de tu herramienta no llega en unos 4 minutos, la llamada pendiente lanza un `TimeoutError` dentro del código en ejecución de Claude. Claude ve el error en `stderr` y normalmente reintenta la llamada:

```json
{
  "type": "code_execution_tool_result",
  "tool_use_id": "srvtoolu_abc123",
  "content": {
    "type": "code_execution_result",
    "stdout": "",
    "stderr": "TimeoutError: Calling tool ['query_database'] timed out (no response after 270s).",
    "return_code": 0,
    "content": []
  }
}
```

Para evitar los tiempos de espera agotados:

* Monitorea el campo `expires_at` en las respuestas
* Implementa tiempos de espera para la ejecución de tus herramientas
* Considera dividir las operaciones largas en partes más pequeñas

### Errores de ejecución de herramientas

Si tu herramienta devuelve un error:

```json
{
  "type": "tool_result",
  "tool_use_id": "toolu_abc123",
  "content": "Error: Query timeout - table lock exceeded 30 seconds"
}
```

El código de Claude recibe este error y puede manejarlo de forma apropiada.

## Restricciones y limitaciones

### Incompatibilidades de funcionalidades

* **Salidas estructuradas:** Las herramientas con `strict: true` no son compatibles con la llamada programática
* **Elección de herramienta:** No puedes forzar la llamada programática de una herramienta específica mediante `tool_choice`
* **Uso de herramientas en paralelo:** `disable_parallel_tool_use: true` no es compatible con la llamada programática

### Limitaciones del esquema de entrada

Las herramientas personalizadas cuyo `input_schema` contiene un `$ref` recursivo (un ciclo de referencias, como un esquema que se refiere a sí mismo) no pueden habilitarse para la llamada programática. Incluir una versión de la herramienta de ejecución de código en `allowed_callers` para una herramienta así hace que la solicitud falle con un `400 invalid_request_error` cuyo mensaje contiene `Circular $ref detected`. El mismo esquema se acepta para la llamada directa de herramientas.

Para solucionar esto, haz una de las siguientes cosas:

* Mantén la herramienta solo como directa omitiendo `allowed_callers` (o estableciéndolo en `["direct"]`). Otras herramientas en la misma solicitud aún pueden usar la llamada programática.
* Elimina el ciclo del esquema. Por ejemplo, desenrolla la recursión hasta una profundidad fija y describe cualquier anidamiento más profundo en la `description` del nivel más interno, o reemplaza la propiedad recursiva con un simple `{"type": "object"}` cuya `description` explique la forma esperada.

### Restricciones de herramientas

Las siguientes herramientas no pueden llamarse de forma programática:

* Herramientas proporcionadas por un [conector MCP](https://platform.claude.com/docs/es/agents-and-tools/mcp-connector)
* Los conjuntos de herramientas de [uso de computadora](https://platform.claude.com/docs/es/agents-and-tools/tool-use/computer-use-tool) y [uso de navegador](https://platform.claude.com/docs/es/agents-and-tools/tool-use/browser-use-tool) (`computer_toolset_20260801` y `browser_toolset_20260801`), cuyo campo `allowed_callers` acepta solo `"direct"`

### Restricciones de formato de mensajes

Al responder a llamadas programáticas de herramientas, existen requisitos de formato estrictos:

**Respuestas solo con resultados de herramientas:** Si hay llamadas programáticas de herramientas pendientes esperando resultados, tu mensaje de respuesta debe contener **solo** bloques `tool_result`. No puedes incluir ningún contenido de texto, ni siquiera después de los resultados de las herramientas.

No válido - No se puede incluir texto al responder a llamadas programáticas de herramientas:

```json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01",
      "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"
    },
    { "type": "text", "text": "What should I do next?" }
  ]
}
```

Válido - Solo resultados de herramientas al responder a llamadas programáticas de herramientas:

```json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01",
      "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"
    }
  ]
}
```

Esta restricción solo se aplica al responder a llamadas de herramientas programáticas (de ejecución de código). Para las llamadas de herramientas regulares del lado del cliente, puedes incluir contenido de texto después de los resultados de las herramientas.

**Contenido de resultado de herramienta solo de texto:** El `content` de cada `tool_result` que responde a una llamada programática debe ser una cadena o bloques `text`. Los bloques de imagen, documento y otros tipos de bloques de contenido se rechazan.

### Límites de velocidad

Las llamadas programáticas de herramientas están sujetas a los mismos "rate limits" (límites de velocidad) que las llamadas de herramientas regulares. Cada llamada a herramienta desde la ejecución de código cuenta como una invocación separada.

### Valida los resultados de las herramientas antes de usarlos

Al implementar herramientas definidas por el usuario que se llamarán de forma programática:

* **Los resultados de las herramientas se devuelven como cadenas:** Pueden contener cualquier contenido, incluidos fragmentos de código o comandos ejecutables que podrían ser procesados por el entorno de ejecución.
* **Valida los resultados de herramientas externas:** Si tu herramienta devuelve datos de fuentes externas o acepta entradas del usuario, ten en cuenta los riesgos de inyección de código si la salida se interpretará o ejecutará como código.

## Eficiencia de tokens

La llamada programática de herramientas reduce el consumo de tokens de tres maneras:

* **Los resultados de herramientas de las llamadas programáticas no se agregan al contexto de Claude** - solo la salida final del código
* **El procesamiento intermedio ocurre en código** - el filtrado, la agregación y otras transformaciones no consumen tokens del modelo
* **Múltiples llamadas a herramientas en una sola ejecución de código** - reduce la sobrecarga en comparación con turnos separados del modelo

Por ejemplo, llamar a 10 herramientas directamente usa \~10 veces los tokens de llamarlas de forma programática y devolver un resumen.

En las evaluaciones internas de Anthropic sobre un modelo Claude de producción:

* En un benchmark de agente de gestión de proyectos con 75 herramientas, habilitar la llamada programática de herramientas redujo los tokens de entrada facturados en aproximadamente un 38% sin cambios en la precisión de las tareas.
* En [τ²-bench](https://arxiv.org/abs/2506.07982) (dominios de aerolíneas, comercio minorista y telecomunicaciones), donde cada turno realiza una o dos llamadas a herramientas secuenciales, la llamada programática de herramientas dejó las puntuaciones sin cambios y costó aproximadamente un 8% más. Los flujos de trabajo secuenciales de una sola llamada no se benefician.
* En el tráfico de producción de la API, las solicitudes cuyo arreglo `tools` contiene de 10 a 49 definiciones de herramientas ven ahorros típicos de tokens del 20% al 40% con la llamada programática de herramientas habilitada.

Los ahorros reales varían según la forma de la carga de trabajo. Consulta [Cuándo usar la llamada programática](https://platform.claude.com/docs/es/agents-and-tools/tool-use/programmatic-tool-calling#when-to-use-programmatic-calling).

## Uso y precios

La llamada programática de herramientas usa los mismos precios que la ejecución de código. Consulta los [precios de la ejecución de código](https://platform.claude.com/docs/es/agents-and-tools/tool-use/code-execution-tool#usage-and-pricing) para más detalles.

<Note>
  Conteo de tokens para llamadas programáticas de herramientas: Los resultados de herramientas de las invocaciones programáticas no cuentan para tu uso de tokens de entrada/salida. Solo cuentan el resultado final de la ejecución de código y la respuesta de Claude.
</Note>

## Mejores prácticas

### Diseño de herramientas

* **Proporciona descripciones detalladas de la salida:** Dado que Claude deserializa los resultados de las herramientas en código, documenta el formato (estructura JSON y tipos de campos)
* **Devuelve datos estructurados:** JSON u otros formatos legibles por máquina funcionan mejor para el procesamiento programático
* **Mantén las respuestas concisas:** Devuelve solo los datos necesarios para minimizar la sobrecarga de procesamiento

### Cuándo usar la llamada programática

La llamada programática de herramientas intercambia una pequeña sobrecarga fija (inicio del contenedor, generación del script) por grandes ahorros en tokens de resultados de herramientas y viajes de ida y vuelta al modelo. Si ese intercambio vale la pena depende de la forma de la carga de trabajo.

**Buen ajuste:**

* Operaciones de distribución (fan-out) o en paralelo sobre muchos elementos (por ejemplo, verificar 50 endpoints o buscar 20 registros)
* Resultados de herramientas grandes que pueden filtrarse, agregarse o resumirse antes de llegar al contexto de Claude
* Búsqueda y recuperación agéntica, donde las consultas iterativas y el filtrado de resultados dominan el flujo de trabajo

**Mal ajuste:**

* Flujos de trabajo estrictamente secuenciales donde cada llamada depende de que Claude razone sobre el resultado anterior, porque el script no puede omitir el viaje de ida y vuelta al modelo en ese caso
* Un número pequeño de llamadas a herramientas con respuestas pequeñas, especialmente en el primer turno de una conversación, donde la sobrecarga del contenedor y del script puede superar los ahorros
* Herramientas que requieren retroalimentación inmediata del usuario entre llamadas

Si no estás seguro, mide los tokens de entrada facturados con y sin `allowed_callers` en una muestra representativa de tu tráfico antes de habilitarlo de forma generalizada.

### Optimización del rendimiento

* **Reutiliza los contenedores** al realizar múltiples solicitudes relacionadas para mantener el estado
* **Agrupa operaciones similares** en una sola ejecución de código cuando sea posible

## Solución de problemas

### Problemas comunes

**`invalid_request_error` al establecer `tool_choice`**

* `tool_choice` no puede nombrar una herramienta cuyo `allowed_callers` omita `"direct"`. Agrega `"direct"` al `allowed_callers` de esa herramienta, o elimina la herramienta de `tool_choice` y deja que Claude la invoque desde código.

**Expiración del contenedor**

* Responde a cada llamada programática de herramienta mucho antes de la marca de tiempo `expires_at` de la respuesta pausada. El código de Claude deja de esperar un resultado después de unos 4 minutos, y actualmente los contenedores inactivos se recuperan después de unos 5 minutos.
* Considera implementar una ejecución de herramientas más rápida

**El resultado de la herramienta no se analiza correctamente**

* Asegúrate de que tu herramienta devuelva datos de cadena que Claude pueda deserializar
* Proporciona documentación clara del formato de salida en la descripción de tu herramienta

### Consejos de depuración

1. **Registra todas las llamadas a herramientas y sus resultados** para seguir el flujo
2. **Revisa el campo `caller`** para confirmar la invocación programática
3. **Monitorea los ID de contenedor** para asegurar una reutilización adecuada
4. **Prueba las herramientas de forma independiente** antes de habilitar la llamada programática

## Por qué funciona la llamada programática de herramientas

Claude está entrenado con grandes cantidades de código, por lo que presentar las herramientas como funciones de Python invocables le permite aprovechar esa fortaleza:

* **Composición de herramientas:** Las llamadas encadenadas, los bucles y los condicionales son flujo de control ordinario de Python en lugar de una serie de viajes de ida y vuelta al modelo
* **Procesamiento de resultados:** El código de Claude filtra y agrega salidas grandes de herramientas, o las escribe en archivos, y solo la salida final entra en la ventana de contexto
* **Latencia:** El modelo no se vuelve a muestrear entre las llamadas a herramientas dentro de una misma ejecución de código

## Implementaciones alternativas

La llamada programática de herramientas es un patrón generalizable que también puede implementarse en tu propia infraestructura. Así se comparan los enfoques:

### Ejecución directa del lado del cliente

Proporciona a Claude una herramienta de ejecución de código y describe qué funciones están disponibles en ese entorno. Cuando Claude invoca la herramienta con código, tu aplicación lo ejecuta localmente donde esas funciones están definidas.

**Ventajas:**

* Mínima reestructuración de tu aplicación
* Control total sobre el entorno y las instrucciones

**Desventajas:**

* Ejecuta código no confiable fuera de un sandbox
* Las invocaciones de herramientas pueden ser vectores de inyección de código

**Úsalo cuando:** Tu aplicación puede ejecutar código arbitrario de forma segura, quieres la implementación más pequeña y la oferta administrada de Anthropic no se ajusta a tus necesidades.

### Ejecución en sandbox autogestionada

El mismo enfoque desde la perspectiva de Claude, pero el código se ejecuta en un contenedor aislado con restricciones de seguridad (por ejemplo, sin salida de red). Si tus herramientas requieren recursos externos, necesitarás un protocolo para ejecutar las llamadas a herramientas fuera del sandbox.

**Ventajas:**

* Llamada programática de herramientas segura en tu propia infraestructura
* Control total sobre el entorno de ejecución

**Desventajas:**

* Complejo de construir y mantener
* Requiere gestionar tanto la infraestructura como la comunicación entre procesos

**Úsalo cuando:** La seguridad es crítica y la solución administrada de Anthropic no se ajusta a tus requisitos.

### Ejecución administrada por Anthropic

La llamada programática de herramientas de Anthropic es una versión administrada de la ejecución en sandbox con un entorno de Python con criterios definidos y ajustado para Claude. Anthropic se encarga de la gestión de contenedores, la ejecución de código y la comunicación segura de invocación de herramientas.

**Ventajas:**

* Seguro y protegido por defecto
* Se habilita con una definición de herramienta, sin infraestructura que operar
* Entorno e instrucciones optimizados para Claude

Considera usar la solución administrada de Anthropic si usas la Claude API, [Claude Platform en AWS](https://platform.claude.com/docs/es/build-with-claude/claude-platform-on-aws) o [Microsoft Foundry](https://platform.claude.com/docs/es/build-with-claude/claude-in-microsoft-foundry). En Microsoft Foundry, la llamada programática de herramientas requiere un [despliegue Hosted on Anthropic](https://platform.claude.com/docs/es/build-with-claude/claude-in-microsoft-foundry#additional-features-not-supported-when-hosted-on-azure).

## Retención de datos

La llamada programática de herramientas está construida sobre la infraestructura de ejecución de código y usa los mismos contenedores sandbox. Los datos del contenedor, incluidos los artefactos de ejecución y las salidas, se retienen hasta por 30 días.

Para la elegibilidad de ZDR en todas las funcionalidades, consulta [API y retención de datos](https://platform.claude.com/docs/es/manage-claude/api-and-data-retention).

## Próximos pasos

<CardGroup cols={2}>
  <Card title="Streaming de herramientas de grano fino" icon="bolt" href="https://platform.claude.com/docs/es/agents-and-tools/tool-use/fine-grained-tool-streaming">
    Transmite por streaming las entradas de herramientas sin almacenamiento en búfer de JSON del lado del servidor para aplicaciones sensibles a la latencia.
  </Card>

  <Card title="Herramienta de ejecución de código" icon="code" href="https://platform.claude.com/docs/es/agents-and-tools/tool-use/code-execution-tool">
    Ejecuta código Python y bash en un contenedor aislado para analizar datos, generar archivos e iterar sobre soluciones.
  </Card>

  <Card title="Uso de herramientas con Claude" icon="wrench" href="https://platform.claude.com/docs/es/agents-and-tools/tool-use/overview">
    Conecta Claude a herramientas y APIs externas. Consulta dónde se ejecutan las herramientas, cuándo las llama Claude y qué herramienta se ajusta a tu tarea.
  </Card>

  <Card title="Definir herramientas" icon="hammer" href="https://platform.claude.com/docs/es/agents-and-tools/tool-use/define-tools">
    Especifica esquemas de herramientas, escribe descripciones efectivas y controla cuándo Claude llama a tus herramientas.
  </Card>
</CardGroup>
