Skip to content

Conversation

@ryx2
Copy link
Contributor

@ryx2 ryx2 commented Dec 3, 2025

Summary

This adds support for Anthropic's programmatic tool calling feature, allowing tools to be called from within code execution blocks.

Part 3 of 3 - Following the review recommendations on #3550, splitting into:

  1. PR Add examples field to ToolDefinition and send it to Anthropic #3619: input_examples feature
  2. PR feat: Add ToolSearchTool and defer_loading for dynamic tool discovery #3620: Tool Search + defer_loading feature
  3. This PR: Programmatic Tool Calling (programmatically_callable)

Changes

  • Add programmatically_callable field to ToolDefinition dataclass

    • False (default): Tool can only be called directly by the model
    • True: Tool callable both directly and from code execution
    • 'only': Tool only callable from code execution
  • Add programmatically_callable parameter to:

    • Tool class constructor
    • FunctionToolset.add_function() and @tool decorator
    • Agent.tool() and Agent.tool_plain() decorators
  • Update Anthropic model:

    • Map programmatically_callable to Anthropic's allowed_callers API
    • Auto-add CodeExecutionTool when programmatically_callable is used
    • Use newer code execution tool (20250825) when PTC is enabled
    • Store caller and container_id in ToolCallPart.provider_details for tools called from code execution

Example Usage

from pydantic_ai import Agent
from pydantic_ai.builtin_tools import CodeExecutionTool

agent = Agent('anthropic:claude-sonnet-4-5', builtin_tools=[CodeExecutionTool()])

# Tool callable both directly by model and from code execution
@agent.tool_plain(programmatically_callable=True)
def add_numbers(x: int, y: int) -> int:
    """Add two numbers."""
    return x + y

# Tool only callable from code execution (not directly by model)
@agent.tool_plain(programmatically_callable='only')
def calculate_pi(precision: int) -> float:
    """Calculate pi to given precision."""
    # Only code execution can call this
    return 3.14159265358979

Test plan

  • Added unit tests for programmatically_callable values (True, 'only', False)
  • Added test for auto-adding CodeExecutionTool when PTC is used
  • Added tests verifying correct code execution tool version is used
  • All existing tests pass

🤖 Generated with Claude Code

This adds support for Anthropic's programmatic tool calling feature,
allowing tools to be called from within code execution blocks.

Changes:
- Add `programmatically_callable` field to `ToolDefinition` dataclass
  - `False` (default): Tool can only be called directly by the model
  - `True`: Tool callable both directly and from code execution
  - `'only'`: Tool only callable from code execution

- Add `programmatically_callable` parameter to:
  - `Tool` class constructor
  - `FunctionToolset.add_function()` and `@tool` decorator
  - `Agent.tool()` and `Agent.tool_plain()` decorators

- Update Anthropic model:
  - Map `programmatically_callable` to Anthropic's `allowed_callers` API
  - Auto-add `CodeExecutionTool` when `programmatically_callable` is used
  - Use newer code execution tool (20250825) when PTC is enabled
  - Store `caller` and `container_id` in `ToolCallPart.provider_details`
    for tools called from code execution

- Add comprehensive tests for the feature

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant