Tool use is where the API shape diverges most significantly. OpenAI's `functions` / `tools` format uses a JSON Schema wrapped in a `function` type object. Anthropic's `tools` format uses `name`, `description`, and `input_schema` directly — no extra `function` wrapper level. The response parsing also differs: OpenAI returns `tool_calls` on the assistant message; Anthropic returns `content` blocks of `type='tool_use'`.
Before (OpenAI tool definition):
```python
tools = [{
'type': 'function',
'function': {
'name': 'get_weather',
'description': 'Get current weather for a city',
'parameters': {
'type': 'object',
'properties': {
'city': {'type': 'string', 'description': 'City name'}
},
'required': ['city']
}
}
}]
response = client.chat.completions.create(
model='gpt-5', messages=msgs, tools=tools
)
# Parsing the tool call:
tool_call = response.choices[0].message.tool_calls[0]
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
```
After (Anthropic tool definition):
```python
tools = [{
'name': 'get_weather',
'description': 'Get current weather for a city',
'input_schema': {
'type': 'object',
'properties': {
'city': {'type': 'string', 'description': 'City name'}
},
'required': ['city']
}
}]
response = client.messages.create(
model='claude-sonnet-4-6',
max_tokens=1024,
messages=msgs,
tools=tools
)
# Parsing the tool call:
tool_block = next(b for b in response.content if b.type == 'tool_use')
func_name = tool_block.name
func_args = tool_block.input # already a dict, no json.loads needed
```
Returning tool results also differs. OpenAI expects a `role='tool'` message with `tool_call_id`. Anthropic expects a `role='user'` message containing a `content` block of `type='tool_result'` with the `tool_use_id`.
Before (OpenAI tool result):
```python
msgs.append(response.choices[0].message) # append assistant turn
msgs.append({
'role': 'tool',
'tool_call_id': tool_call.id,
'content': json.dumps({'temperature': '72F', 'condition': 'sunny'})
})
```
After (Anthropic tool result):
```python
msgs.append({'role': 'assistant', 'content': response.content})
msgs.append({
'role': 'user',
'content': [{
'type': 'tool_result',
'tool_use_id': tool_block.id,
'content': json.dumps({'temperature': '72F', 'condition': 'sunny'})
}]
})
```
The full tool use flow is documented at docs.anthropic.com/en/docs/tool-use. The pattern is consistent across all Claude models including Haiku 4.5, Sonnet 4.6, and Opus 4.8.