claudette

Claudette is Claude’s friend

NB: If you are reading this in GitHub’s readme, we recommend you instead read the much more nicely formatted documentation format of this tutorial.

Claudette is a wrapper for Anthropic’s Python SDK.

The SDK works well, but it is quite low level – it leaves the developer to do a lot of stuff manually. That’s a lot of extra work and boilerplate! Claudette automates pretty much everything that can be automated, whilst providing full control. Amongst the features provided:

You’ll need to set the ANTHROPIC_API_KEY environment variable to the key provided to you by Anthropic in order to use this library.

Note that this library is the first ever “literate nbdev” project. That means that the actual source code for the library is a rendered Jupyter Notebook which includes callout notes and tips, HTML tables and images, detailed explanations, and teaches how and why the code is written the way it is. Even if you’ve never used the Anthropic Python SDK or Claude API before, you should be able to read the source code. Click Claudette’s Source to read it, or clone the git repo and execute the notebook yourself to see every step of the creation process in action. The tutorial below includes links to API details which will take you to relevant parts of the source. The reason this project is a new kind of literal program is because we take seriously Knuth’s call to action, that we have a “moral commitment” to never write an “illiterate program” – and so we have a commitment to making literate programming and easy and pleasant experience. (For more on this, see this talk from Hamel Husain.)

Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.” Donald E. Knuth, Literate Programming (1984)

Install

pip install claudette

Getting started

Anthropic’s Python SDK will automatically be installed with Claudette, if you don’t already have it.

import os
# os.environ['ANTHROPIC_LOG'] = 'debug'

To print every HTTP request and response in full, uncomment the above line.

from claudette import *

Claudette only exports the symbols that are needed to use the library, so you can use import * to import them. Alternatively, just use:

import claudette

…and then add the prefix claudette. to any usages of the module.

Claudette provides models, which is a list of models currently available from the SDK.

models
['claude-3-opus-20240229',
 'claude-3-7-sonnet-20250219',
 'claude-3-5-sonnet-20241022',
 'claude-3-haiku-20240307',
 'claude-3-5-haiku-20241022']

For these examples, we’ll use Sonnet 3.5, since it’s awesome!

model = models[1]

Chat

The main interface to Claudette is the Chat class, which provides a stateful interface to Claude:

chat = Chat(model, sp="""You are a helpful and concise assistant.""")
chat("I'm Jeremy")

Hello, Jeremy! How can I assist you today?

  • id: msg_01JKhMQx949VK4aVMGdh2x59
  • content: [{'citations': None, 'text': 'Hello, Jeremy! How can I assist you today?', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 19, 'output_tokens': 14}
r = chat("What's my name?")
r

Your name is Jeremy, as you mentioned in your introduction.

  • id: msg_01W5rc2j8EAQDFzZWfg1Dikx
  • content: [{'citations': None, 'text': 'Your name is Jeremy, as you mentioned in your introduction.', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 41, 'output_tokens': 15}
r = chat("What's my name?")
r

Your name is Jeremy.

  • id: msg_01CFQui4Zobt3WYs7qbUBvyh
  • content: [{'citations': None, 'text': 'Your name is Jeremy.', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 64, 'output_tokens': 8}

As you see above, displaying the results of a call in a notebook shows just the message contents, with the other details hidden behind a collapsible section. Alternatively you can print the details:

print(r)
Message(id='msg_01CFQui4Zobt3WYs7qbUBvyh', content=[TextBlock(citations=None, text='Your name is Jeremy.', type='text')], model='claude-3-7-sonnet-20250219', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 64; Out: 8; Cache create: 0; Cache read: 0; Total: 72)

Claude supports adding an extra assistant message at the end, which contains the prefill – i.e. the text we want Claude to assume the response starts with. Let’s try it out:

chat("Concisely, what is the meaning of life?",
     prefill='According to Douglas Adams,')

According to Douglas Adams, 42. Philosophically, it’s often considered to be finding personal meaning, happiness, and fulfillment through relationships, purpose, and experiences.

  • id: msg_01HtFZp54GYJdfopa4vweb1G
  • content: [{'citations': None, 'text': "According to Douglas Adams, 42. Philosophically, it's often considered to be finding personal meaning, happiness, and fulfillment through relationships, purpose, and experiences.", 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 92, 'output_tokens': 34}

You can add stream=True to stream the results as soon as they arrive (although you will only see the gradual generation if you execute the notebook yourself, of course!)

for o in chat("Concisely, what book was that in?", prefill='It was in', stream=True):
    print(o, end='')
It was in "The Hitchhiker's Guide to the Galaxy" by Douglas Adams.

Async

Alternatively, you can use AsyncChat (or AsyncClient) for the async versions, e.g:

chat = AsyncChat(model)
await chat("I'm Jeremy")

Hello, Jeremy! It’s nice to meet you. How are you doing today? Is there something I can help you with or would you like to chat about something specific?

  • id: msg_01PqUxGc9uiZVxy6EChRXcuy
  • content: [{'citations': None, 'text': "Hello, Jeremy! It's nice to meet you. How are you doing today? Is there something I can help you with or would you like to chat about something specific?", 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 38}

Remember to use async for when streaming in this case:

async for o in await chat("Concisely, what is the meaning of life?",
                          prefill='According to Douglas Adams,', stream=True):
    print(o, end='')
According to Douglas Adams,  42. More seriously, the meaning of life is likely what you create through your relationships, pursuits, and values that bring you fulfillment and purpose.

Prompt caching

If you use mk_msg(msg, cache=True), then the message is cached using Claude’s prompt caching feature. For instance, here we use caching when asking about Claudette’s readme file:

chat = Chat(model, sp="""You are a helpful and concise assistant.""")
nbtxt = Path('README.txt').read_text()
msg = f'''<README>
{nbtxt}
</README>
In brief, what is the purpose of this project based on the readme?'''
r = chat(mk_msg(msg, cache=True))
r

Claudette is a high-level wrapper for Anthropic’s Python SDK that automates common tasks and provides additional functionality. Its main features include:

  1. A Chat class for stateful dialogs
  2. Support for prefill (controlling Claude’s initial response words)
  3. Convenient image handling
  4. Simple tool use API integration

The project is notable for being the first “literate nbdev” project, meaning its source code is written as a detailed, readable Jupyter Notebook that includes explanations, examples, and teaching material alongside the functional code.

The goal is to simplify working with Claude’s API while maintaining full control, reducing boilerplate code and manual work that would otherwise be needed with the base SDK.

  • id: msg_018FtfRtRxkWRdEK69qnASgC
  • content: [{'citations': None, 'text': 'Claudette is a high-level wrapper for Anthropic\'s Python SDK that automates common tasks and provides additional functionality. Its main features include:\n\n1. A Chat class for stateful dialogs\n2. Support for prefill (controlling Claude\'s initial response words)\n3. Convenient image handling\n4. Simple tool use API integration\n\nThe project is notable for being the first "literate nbdev" project, meaning its source code is written as a detailed, readable Jupyter Notebook that includes explanations, examples, and teaching material alongside the functional code.\n\nThe goal is to simplify working with Claude\'s API while maintaining full control, reducing boilerplate code and manual work that would otherwise be needed with the base SDK.', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 9287, 'cache_read_input_tokens': 0, 'input_tokens': 4, 'output_tokens': 157}

The response records the a cache has been created using these input tokens:

print(r.usage)
Usage(cache_creation_input_tokens=9287, cache_read_input_tokens=0, input_tokens=4, output_tokens=157)

We can now ask a followup question in this chat:

r = chat('How does it make tool use more ergonomic?')
r

According to the README, Claudette makes tool use more ergonomic in several ways:

  1. It uses docments to make Python function definitions more user-friendly - each parameter and return value should have a type and description

  2. It handles the tool calling process automatically - when Claude returns a tool_use message, Claudette manages calling the tool with the provided parameters behind the scenes

  3. It provides a toolloop method that can handle multiple tool calls in a single step to solve more complex problems

  4. It allows you to pass a list of tools to the Chat constructor and optionally force Claude to always use a specific tool via tool_choice

Here’s a simple example from the README:

def sums(
    a:int,  # First thing to sum 
    b:int=1 # Second thing to sum
) -> int: # The sum of the inputs
    "Adds a + b."
    print(f"Finding the sum of {a} and {b}")
    return a + b

chat = Chat(model, sp=sp, tools=[sums], tool_choice='sums')

This makes it much simpler compared to manually handling all the tool use logic that would be required with the base SDK.

  • id: msg_011hEtdB23ptoEaWyHgk4m2k
  • content: [{'citations': None, 'text': 'According to the README, Claudette makes tool use more ergonomic in several ways:\n\n1. It uses docments to make Python function definitions more user-friendly - each parameter and return value should have a type and description\n\n2. It handles the tool calling process automatically - when Claude returns a tool_use message, Claudette manages calling the tool with the provided parameters behind the scenes\n\n3. It provides atoolloopmethod that can handle multiple tool calls in a single step to solve more complex problems\n\n4. It allows you to pass a list of tools to the Chat constructor and optionally force Claude to always use a specific tool viatool_choice\n\nHere\'s a simple example from the README:\n\n```python\ndef sums(\n a:int, # First thing to sum \n b:int=1 # Second thing to sum\n) -> int: # The sum of the inputs\n "Adds a + b."\n print(f"Finding the sum of {a} and {b}")\n return a + b\n\nchat = Chat(model, sp=sp, tools=[sums], tool_choice=\'sums\')\n```\n\nThis makes it much simpler compared to manually handling all the tool use logic that would be required with the base SDK.', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 9287, 'input_tokens': 175, 'output_tokens': 280}

We can see that this only used ~200 regular input tokens – the 7000+ context tokens have been read from cache.

print(r.usage)
Usage(cache_creation_input_tokens=0, cache_read_input_tokens=9287, input_tokens=175, output_tokens=280)
chat.use
In: 179; Out: 437; Cache create: 9287; Cache read: 9287; Total: 19190

Tool use

Tool use lets Claude use external tools.

We use docments to make defining Python functions as ergonomic as possible. Each parameter (and the return value) should have a type, and a docments comment with the description of what it is. As an example we’ll write a simple function that adds numbers together, and will tell us when it’s being called:

def sums(
    a:int,  # First thing to sum
    b:int=1 # Second thing to sum
) -> int: # The sum of the inputs
    "Adds a + b."
    print(f"Finding the sum of {a} and {b}")
    return a + b

Sometimes Claude will say something like “according to the sums tool the answer is” – generally we’d rather it just tells the user the answer, so we can use a system prompt to help with this:

sp = "Never mention what tools you use."

We’ll get Claude to add up some long numbers:

a,b = 604542,6458932
pr = f"What is {a}+{b}?"
pr
'What is 604542+6458932?'

To use tools, pass a list of them to Chat:

chat = Chat(model, sp=sp, tools=[sums])

To force Claude to always answer using a tool, set tool_choice to that function name. When Claude needs to use a tool, it doesn’t return the answer, but instead returns a tool_use message, which means we have to call the named tool with the provided parameters.

r = chat(pr, tool_choice='sums')
r
Finding the sum of 604542 and 6458932

ToolUseBlock(id=‘toolu_01915nm3QDrQH1GSzVU7Xvqt’, input={‘a’: 604542, ‘b’: 6458932}, name=‘sums’, type=‘tool_use’)

  • id: msg_01JP7GyAbS9Tp1UCYD9dwThU
  • content: [{'id': 'toolu_01915nm3QDrQH1GSzVU7Xvqt', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: tool_use
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 442, 'output_tokens': 53}

Claudette handles all that for us – we just call it again, and it all happens automatically:

chat()

The sum of 604542 and 6458932 is 7,063,474.

  • id: msg_01RDhvKv8wUn5pfC5p1CxTxz
  • content: [{'citations': None, 'text': 'The sum of 604542 and 6458932 is 7,063,474.', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 524, 'output_tokens': 25}

You can see how many tokens have been used at any time by checking the use property. Note that (as of May 2024) tool use in Claude uses a lot of tokens, since it automatically adds a large system prompt.

chat.use
In: 966; Out: 78; Cache create: 0; Cache read: 0; Total: 1044

We can do everything needed to use tools in a single step, by using Chat.toolloop. This can even call multiple tools as needed solve a problem. For example, let’s define a tool to handle multiplication:

def mults(
    a:int,  # First thing to multiply
    b:int=1 # Second thing to multiply
) -> int: # The product of the inputs
    "Multiplies a * b."
    print(f"Finding the product of {a} and {b}")
    return a * b

Now with a single call we can calculate (a+b)*2 – by passing show_trace we can see each response from Claude in the process:

chat = Chat(model, sp=sp, tools=[sums,mults])
pr = f'Calculate ({a}+{b})*2'
pr
'Calculate (604542+6458932)*2'
chat.toolloop(pr, trace_func=print)
Finding the sum of 604542 and 6458932
[{'role': 'user', 'content': 'Calculate (604542+6458932)*2'}, {'role': 'assistant', 'content': [TextBlock(citations=None, text="I'll calculate (604542+6458932)*2 for you.\n\nFirst, let me add the numbers inside the parentheses:", type='text'), ToolUseBlock(id='toolu_01SkhYBiVNDAbCPkX3be6X4F', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01SkhYBiVNDAbCPkX3be6X4F', 'content': '7063474'}]}]
Finding the product of 7063474 and 2
[{'role': 'assistant', 'content': [TextBlock(citations=None, text="Now, I'll multiply this result by 2:", type='text'), ToolUseBlock(id='toolu_01XaagwWimhXuMt2oKMBttWv', input={'a': 7063474, 'b': 2}, name='mults', type='tool_use')]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01XaagwWimhXuMt2oKMBttWv', 'content': '14126948'}]}]
[{'role': 'assistant', 'content': [TextBlock(citations=None, text='The result of (604542+6458932)*2 is 14,126,948.', type='text')]}]

The result of (604542+6458932)*2 is 14,126,948.

  • id: msg_015TzicGDqJnYbYEmVyxPMvd
  • content: [{'citations': None, 'text': 'The result of (604542+6458932)*2 is 14,126,948.', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 752, 'output_tokens': 25}

Structured data

If you just want the immediate result from a single tool, use Client.structured.

cli = Client(model)
def sums(
    a:int,  # First thing to sum
    b:int=1 # Second thing to sum
) -> int: # The sum of the inputs
    "Adds a + b."
    print(f"Finding the sum of {a} and {b}")
    return a + b
cli.structured("What is 604542+6458932", sums)
Finding the sum of 604542 and 6458932
[7063474]

This is particularly useful for getting back structured information, e.g:

class President:
    "Information about a president of the United States"
    def __init__(self, 
                first:str, # first name
                last:str, # last name
                spouse:str, # name of spouse
                years_in_office:str, # format: "{start_year}-{end_year}"
                birthplace:str, # name of city
                birth_year:int # year of birth, `0` if unknown
        ):
        assert re.match(r'\d{4}-\d{4}', years_in_office), "Invalid format: `years_in_office`"
        store_attr()

    __repr__ = basic_repr('first, last, spouse, years_in_office, birthplace, birth_year')
cli.structured("Provide key information about the 3rd President of the United States", President)
[President(first='Thomas', last='Jefferson', spouse='Martha Wayles Skelton', years_in_office='1801-1809', birthplace='Shadwell, Virginia', birth_year=1743)]

Images

Claude can handle image data as well. As everyone knows, when testing image APIs you have to use a cute puppy.

fn = Path('samples/puppy.jpg')
display.Image(filename=fn, width=200)

We create a Chat object as before:

chat = Chat(model)

Claudette expects images as a list of bytes, so we read in the file:

img = fn.read_bytes()

Prompts to Claudette can be lists, containing text, images, or both, eg:

chat([img, "In brief, what color flowers are in this image?"])

The image shows purple flowers (appears to be asters or similar purple daisies) blooming next to a small Cavalier King Charles Spaniel puppy. The puppy is resting on grass, and the purple flowers create a nice contrast with the natural setting.

  • id: msg_01MEKVkFVbh1MHZwY2PNy8PQ
  • content: [{'citations': None, 'text': 'The image shows purple flowers (appears to be asters or similar purple daisies) blooming next to a small Cavalier King Charles Spaniel puppy. The puppy is resting on grass, and the purple flowers create a nice contrast with the natural setting.', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 110, 'output_tokens': 60}

The image is included as input tokens.

chat.use
In: 110; Out: 60; Cache create: 0; Cache read: 0; Total: 170

Alternatively, Claudette supports creating a multi-stage chat with separate image and text prompts. For instance, you can pass just the image as the initial prompt (in which case Claude will make some general comments about what it sees), and then follow up with questions in additional prompts:

chat = Chat(model)
chat(img)

This is an adorable puppy with a white and brown coat, resting on some grass. The puppy appears to be a Cavalier King Charles Spaniel or similar breed, with distinctive brown patches on its ears and around one eye. The puppy has a sweet expression and is lying near some purple flowers, likely asters or similar small daisy-like blooms. The setting creates a charming garden scene with the natural elements of grass, flowers, and what looks like a stone or wooden structure in the background. The combination of the cute puppy and the pretty flowers makes for a very heartwarming image.

  • id: msg_01CXq96V9U2Jstf578znibrt
  • content: [{'citations': None, 'text': 'This is an adorable puppy with a white and brown coat, resting on some grass. The puppy appears to be a Cavalier King Charles Spaniel or similar breed, with distinctive brown patches on its ears and around one eye. The puppy has a sweet expression and is lying near some purple flowers, likely asters or similar small daisy-like blooms. The setting creates a charming garden scene with the natural elements of grass, flowers, and what looks like a stone or wooden structure in the background. The combination of the cute puppy and the pretty flowers makes for a very heartwarming image.', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 98, 'output_tokens': 132}
chat('What direction is the puppy facing?')

The puppy is facing toward the camera/viewer, with its head slightly angled. You can see its face clearly with both eyes visible, and its front paws are extended forward on the grass. The puppy’s body is positioned in a relaxed lying down pose with its face as the focal point of the image.

  • id: msg_01L6qPiQqqoBUTVCfm2nqg7S
  • content: [{'citations': None, 'text': "The puppy is facing toward the camera/viewer, with its head slightly angled. You can see its face clearly with both eyes visible, and its front paws are extended forward on the grass. The puppy's body is positioned in a relaxed lying down pose with its face as the focal point of the image.", 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 241, 'output_tokens': 69}
chat('What color is it?')

The puppy has a white and brown coat. Its body is predominantly white, while it has rich brown/chestnut coloring on its ears and a patch around one eye. This color pattern is typical of Cavalier King Charles Spaniels, particularly the Blenheim color variety, which features the characteristic white base with chestnut or reddish-brown markings.

  • id: msg_019z266CT4uu6UCXHsGZ5Qw9
  • content: [{'citations': None, 'text': 'The puppy has a white and brown coat. Its body is predominantly white, while it has rich brown/chestnut coloring on its ears and a patch around one eye. This color pattern is typical of Cavalier King Charles Spaniels, particularly the Blenheim color variety, which features the characteristic white base with chestnut or reddish-brown markings.', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 318, 'output_tokens': 84}

Note that the image is passed in again for every input in the dialog, so that number of input tokens increases quickly with this kind of chat. (For large images, using prompt caching might be a good idea.)

chat.use
In: 657; Out: 285; Cache create: 0; Cache read: 0; Total: 942

Extended Thinking

Claude 3.7 Sonnet has enhanced reasoning capabilities for complex tasks. See docs for more info.

To enable extended thinking simply specify the no. of thinking tokens maxthinktok you want to use.

chat = Chat(first(has_extended_thinking_models))
chat('Write a sentence about Python!', maxthinktok=1024)

Python is a versatile, high-level programming language known for its readable syntax and wide application in data science, web development, artificial intelligence, and automation.

Thinking I’ll write a simple, informative sentence about the Python programming language. I should make it clear that I’m referring to the programming language rather than the snake.
  • id: msg_01Cxug4hSBsiDZ3KWfUkQdUF
  • content: [{'signature': 'ErUBCkYIARgCIkDVNeCzqoRFz0iS5CTiMQA//IJi/R/cq25udwX71lATHFTFTAvaLG7RoQdLaI1cZppD6BTK4VDE30/O007g5DIeEgzZGw7VTS5rOS2jSEYaDDIK0RzCgTZc+bAlsiIw92rY7M6VJ6HtFk898McV6vfOfhcTJkoEBpHFy8WbqJ/HFq8qpwDRGF5HWS5zUSGmKh24Ex0wiBfWEtD/C0q3o02ulDfjJBhqaRfIdWGJjg==', 'thinking': "I'll write a simple, informative sentence about the Python programming language. I should make it clear that I'm referring to the programming language rather than the snake.", 'type': 'thinking'}, {'citations': None, 'text': 'Python is a versatile, high-level programming language known for its readable syntax and wide application in data science, web development, artificial intelligence, and automation.', 'type': 'text'}]
  • model: claude-3-7-sonnet-20250219
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 41, 'output_tokens': 77}
chat.use
In: 41; Out: 77; Cache create: 0; Cache read: 0; Total: 118

Other model providers

You can also use 3rd party providers of Anthropic models, as shown here.

Amazon Bedrock

These are the models available through Bedrock:

models_aws
['claude-3-5-haiku-20241022',
 'claude-3-7-sonnet-20250219',
 'anthropic.claude-3-opus-20240229-v1:0',
 'anthropic.claude-3-5-sonnet-20241022-v2:0']

To use them, call AnthropicBedrock with your access details, and pass that to Client:

from anthropic import AnthropicBedrock
ab = AnthropicBedrock(
    aws_access_key=os.environ['AWS_ACCESS_KEY'],
    aws_secret_key=os.environ['AWS_SECRET_KEY'],
)
client = Client(models_aws[-1], ab)

Now create your Chat object passing this client to the cli parameter – and from then on, everything is identical to the previous examples.

chat = Chat(cli=client)
chat("I'm Jeremy")

Google Vertex

These are the models available through Vertex:

models_goog

To use them, call AnthropicVertex with your access details, and pass that to Client:

from anthropic import AnthropicVertex
import google.auth
project_id = google.auth.default()[1]
gv = AnthropicVertex(project_id=project_id, region="us-east5")
client = Client(models_goog[-1], gv)
chat = Chat(cli=client)
chat("I'm Jeremy")

Extensions