# LangChain Agent Basics

Ref:
- https://docs.langchain.com/oss/python/integrations/providers/anthropic
- https://docs.langchain.com/oss/python/langchain/streaming

This notebook demonstrates how to create and use a LangChain agent with tools.

## Setup

Configure `.env` before running. See `.env.sample`.



```python
import rich
from dotenv import load_dotenv

load_dotenv()
```




    True



## Create Agent

Define a tool and create an agent with `create_agent`.



```python
from datetime import datetime
from typing import Any

from langchain.agents import create_agent
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
from langgraph.graph.state import CompiledStateGraph


@tool
def get_current_time() -> str:
    """Get the current time."""
    return datetime.now().isoformat()


model = ChatAnthropic(model="claude-sonnet-4-5-20250929")
agent: CompiledStateGraph[Any] = create_agent(
    model=model,
    tools=[get_current_time],
    system_prompt="You are a helpful assistant.",
)
```

## Invoke

Run the agent synchronously with `invoke`.



```python
response = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})
rich.print("response =", response)
```


    response =
    {
        'messages': [
            HumanMessage(
                content='Hello!',
                additional_kwargs={},
                response_metadata={},
                id='6ca21649-28d0-41e0-92c7-d8b717fd9c4d'
            ),
            AIMessage(
                content='Hello! How can I help you today?',
                additional_kwargs={},
                response_metadata={
                    'id': 'msg_01KaVjseHKv3bADAMHGbB6eW',
                    'model': 'claude-sonnet-4-5-20250929',
                    'stop_reason': 'end_turn',
                    'stop_sequence': None,
                    'usage': {
                        'cache_creation': {'ephemeral_1h_input_tokens': 0, 'ephemeral_5m_input_tokens': 0},
                        'cache_creation_input_tokens': 0,
                        'cache_read_input_tokens': 0,
                        'input_tokens': 552,
                        'output_tokens': 12,
                        'server_tool_use': None,
                        'service_tier': 'standard'
                    },
                    'model_name': 'claude-sonnet-4-5-20250929',
                    'model_provider': 'anthropic'
                },
                id='lc_run--8133cea3-7c22-4ab9-94c2-7b170ce877a3-0',
                usage_metadata={
                    'input_tokens': 552,
                    'output_tokens': 12,
                    'total_tokens': 564,
                    'input_token_details': {
                        'cache_read': 0,
                        'cache_creation': 0,
                        'ephemeral_5m_input_tokens': 0,
                        'ephemeral_1h_input_tokens': 0
                    }
                }
            )
        ]
    }



## Stream

Stream the agent output with different modes.



```python
# stream_mode="updates" (default) - state updates per node
for chunk in agent.stream({"messages": [{"role": "user", "content": "What time is it?"}]}):
    rich.print("chunk =", chunk)
```


    chunk =
    {
        'model': {
            'messages': [
                AIMessage(
                    content=[
                        {
                            'id': 'toolu_019PSmmz7QNkRFvNL7MQgGdB',
                            'input': {},
                            'name': 'get_current_time',
                            'type': 'tool_use'
                        }
                    ],
                    additional_kwargs={},
                    response_metadata={
                        'id': 'msg_01AhALzvSA8a4QtscKsvsARU',
                        'model': 'claude-sonnet-4-5-20250929',
                        'stop_reason': 'tool_use',
                        'stop_sequence': None,
                        'usage': {
                            'cache_creation': {'ephemeral_1h_input_tokens': 0, 'ephemeral_5m_input_tokens': 0},
                            'cache_creation_input_tokens': 0,
                            'cache_read_input_tokens': 0,
                            'input_tokens': 555,
                            'output_tokens': 38,
                            'server_tool_use': None,
                            'service_tier': 'standard'
                        },
                        'model_name': 'claude-sonnet-4-5-20250929',
                        'model_provider': 'anthropic'
                    },
                    id='lc_run--9647188e-c6ac-4e79-913e-430e964b90ba-0',
                    tool_calls=[
                        {
                            'name': 'get_current_time',
                            'args': {},
                            'id': 'toolu_019PSmmz7QNkRFvNL7MQgGdB',
                            'type': 'tool_call'
                        }
                    ],
                    usage_metadata={
                        'input_tokens': 555,
                        'output_tokens': 38,
                        'total_tokens': 593,
                        'input_token_details': {
                            'cache_read': 0,
                            'cache_creation': 0,
                            'ephemeral_5m_input_tokens': 0,
                            'ephemeral_1h_input_tokens': 0
                        }
                    }
                )
            ]
        }
    }




    chunk =
    {
        'tools': {
            'messages': [
                ToolMessage(
                    content='2025-12-04T07:44:54.404157',
                    name='get_current_time',
                    id='0de4882c-e7b4-49f9-b6c7-083fae568188',
                    tool_call_id='toolu_019PSmmz7QNkRFvNL7MQgGdB'
                )
            ]
        }
    }




    chunk =
    {
        'model': {
            'messages': [
                AIMessage(
                    content='The current time is **7:44 AM** (December 4th, 2025).',
                    additional_kwargs={},
                    response_metadata={
                        'id': 'msg_01MEMbhfapUMp9vcME1u9Bqq',
                        'model': 'claude-sonnet-4-5-20250929',
                        'stop_reason': 'end_turn',
                        'stop_sequence': None,
                        'usage': {
                            'cache_creation': {'ephemeral_1h_input_tokens': 0, 'ephemeral_5m_input_tokens': 0},
                            'cache_creation_input_tokens': 0,
                            'cache_read_input_tokens': 0,
                            'input_tokens': 621,
                            'output_tokens': 24,
                            'server_tool_use': None,
                            'service_tier': 'standard'
                        },
                        'model_name': 'claude-sonnet-4-5-20250929',
                        'model_provider': 'anthropic'
                    },
                    id='lc_run--50c0c808-3ba2-4bd8-8570-0bdaa66f6417-0',
                    usage_metadata={
                        'input_tokens': 621,
                        'output_tokens': 24,
                        'total_tokens': 645,
                        'input_token_details': {
                            'cache_read': 0,
                            'cache_creation': 0,
                            'ephemeral_5m_input_tokens': 0,
                            'ephemeral_1h_input_tokens': 0
                        }
                    }
                )
            ]
        }
    }




```python
# stream_mode="messages" - token-level streaming
for chunk in agent.stream(
    {"messages": [{"role": "user", "content": "What time is it?"}]},
    stream_mode="messages",
):
    rich.print("chunk =", chunk)
```


    chunk =
    (
        AIMessageChunk(
            content=[],
            additional_kwargs={},
            response_metadata={'model_name': 'claude-sonnet-4-5-20250929', 'model_provider': 'anthropic'},
            id='lc_run--849e9a30-851f-44d0-b91d-515995575480'
        ),
        {
            'langgraph_step': 1,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:b588c64e-744a-5f39-8571-71fff68769db',
            'checkpoint_ns': 'model:b588c64e-744a-5f39-8571-71fff68769db',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    chunk =
    (
        AIMessageChunk(
            content=[
                {
                    'id': 'toolu_01NwYdtGcAkSqbfQf5bzp1Hb',
                    'input': {},
                    'name': 'get_current_time',
                    'type': 'tool_use',
                    'index': 0
                }
            ],
            additional_kwargs={},
            response_metadata={'model_provider': 'anthropic'},
            id='lc_run--849e9a30-851f-44d0-b91d-515995575480',
            tool_calls=[
                {'name': 'get_current_time', 'args': {}, 'id': 'toolu_01NwYdtGcAkSqbfQf5bzp1Hb', 'type': 'tool_call'}
            ],
            tool_call_chunks=[
                {
                    'name': 'get_current_time',
                    'args': '',
                    'id': 'toolu_01NwYdtGcAkSqbfQf5bzp1Hb',
                    'index': 0,
                    'type': 'tool_call_chunk'
                }
            ]
        ),
        {
            'langgraph_step': 1,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:b588c64e-744a-5f39-8571-71fff68769db',
            'checkpoint_ns': 'model:b588c64e-744a-5f39-8571-71fff68769db',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    chunk =
    (
        AIMessageChunk(
            content=[{'partial_json': '', 'type': 'input_json_delta', 'index': 0}],
            additional_kwargs={},
            response_metadata={'model_provider': 'anthropic'},
            id='lc_run--849e9a30-851f-44d0-b91d-515995575480',
            tool_calls=[{'name': '', 'args': {}, 'id': None, 'type': 'tool_call'}],
            tool_call_chunks=[{'name': None, 'args': '', 'id': None, 'index': 0, 'type': 'tool_call_chunk'}]
        ),
        {
            'langgraph_step': 1,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:b588c64e-744a-5f39-8571-71fff68769db',
            'checkpoint_ns': 'model:b588c64e-744a-5f39-8571-71fff68769db',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    chunk =
    (
        AIMessageChunk(
            content=[],
            additional_kwargs={},
            response_metadata={'stop_reason': 'tool_use', 'stop_sequence': None, 'model_provider': 'anthropic'},
            id='lc_run--849e9a30-851f-44d0-b91d-515995575480',
            usage_metadata={
                'input_tokens': 555,
                'output_tokens': 38,
                'total_tokens': 593,
                'input_token_details': {'cache_creation': 0, 'cache_read': 0}
            },
            chunk_position='last'
        ),
        {
            'langgraph_step': 1,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:b588c64e-744a-5f39-8571-71fff68769db',
            'checkpoint_ns': 'model:b588c64e-744a-5f39-8571-71fff68769db',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    chunk =
    (
        ToolMessage(
            content='2025-12-04T07:45:00.085107',
            name='get_current_time',
            id='3bcecfd3-bc04-4db6-9c95-18f674c0d231',
            tool_call_id='toolu_01NwYdtGcAkSqbfQf5bzp1Hb'
        ),
        {
            'langgraph_step': 2,
            'langgraph_node': 'tools',
            'langgraph_triggers': ('__pregel_push',),
            'langgraph_path': ('__pregel_push', 0, False),
            'langgraph_checkpoint_ns': 'tools:f57a9720-749c-b3b8-1e26-d2eb09472dbd'
        }
    )




    chunk =
    (
        AIMessageChunk(
            content=[],
            additional_kwargs={},
            response_metadata={'model_name': 'claude-sonnet-4-5-20250929', 'model_provider': 'anthropic'},
            id='lc_run--85c47e36-3e4f-4f9e-b76b-71a54939a91a'
        ),
        {
            'langgraph_step': 3,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    chunk =
    (
        AIMessageChunk(
            content=[{'text': 'The current time is 7', 'type': 'text', 'index': 0}],
            additional_kwargs={},
            response_metadata={'model_provider': 'anthropic'},
            id='lc_run--85c47e36-3e4f-4f9e-b76b-71a54939a91a'
        ),
        {
            'langgraph_step': 3,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    chunk =
    (
        AIMessageChunk(
            content=[{'text': ':45 AM (', 'type': 'text', 'index': 0}],
            additional_kwargs={},
            response_metadata={'model_provider': 'anthropic'},
            id='lc_run--85c47e36-3e4f-4f9e-b76b-71a54939a91a'
        ),
        {
            'langgraph_step': 3,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    chunk =
    (
        AIMessageChunk(
            content=[{'text': '07', 'type': 'text', 'index': 0}],
            additional_kwargs={},
            response_metadata={'model_provider': 'anthropic'},
            id='lc_run--85c47e36-3e4f-4f9e-b76b-71a54939a91a'
        ),
        {
            'langgraph_step': 3,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    chunk =
    (
        AIMessageChunk(
            content=[{'text': ':45) on December 4th', 'type': 'text', 'index': 0}],
            additional_kwargs={},
            response_metadata={'model_provider': 'anthropic'},
            id='lc_run--85c47e36-3e4f-4f9e-b76b-71a54939a91a'
        ),
        {
            'langgraph_step': 3,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    chunk =
    (
        AIMessageChunk(
            content=[{'text': ', 2025.', 'type': 'text', 'index': 0}],
            additional_kwargs={},
            response_metadata={'model_provider': 'anthropic'},
            id='lc_run--85c47e36-3e4f-4f9e-b76b-71a54939a91a'
        ),
        {
            'langgraph_step': 3,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    chunk =
    (
        AIMessageChunk(
            content=[],
            additional_kwargs={},
            response_metadata={'stop_reason': 'end_turn', 'stop_sequence': None, 'model_provider': 'anthropic'},
            id='lc_run--85c47e36-3e4f-4f9e-b76b-71a54939a91a',
            usage_metadata={
                'input_tokens': 621,
                'output_tokens': 28,
                'total_tokens': 649,
                'input_token_details': {'cache_creation': 0, 'cache_read': 0}
            },
            chunk_position='last'
        ),
        {
            'langgraph_step': 3,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'checkpoint_ns': 'model:53b6dc44-33f1-aa07-ce22-afa9a0dc0cd1',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




```python
# stream_mode=["updates", "messages"] - multiple modes
for mode, chunk in agent.stream(
    {"messages": [{"role": "user", "content": "Hello!"}]},
    stream_mode=["updates", "messages"],
):
    rich.print("mode =", repr(mode))
    rich.print("chunk =", chunk)
```


    mode = 'messages'




    chunk =
    (
        AIMessageChunk(
            content=[],
            additional_kwargs={},
            response_metadata={'model_name': 'claude-sonnet-4-5-20250929', 'model_provider': 'anthropic'},
            id='lc_run--efa05280-6c77-4a8e-a0c9-a5c7e6390fbe'
        ),
        {
            'langgraph_step': 1,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:772693e6-6007-0269-aa0f-19acfcdd7244',
            'checkpoint_ns': 'model:772693e6-6007-0269-aa0f-19acfcdd7244',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    mode = 'messages'




    chunk =
    (
        AIMessageChunk(
            content=[{'text': 'Hello! How', 'type': 'text', 'index': 0}],
            additional_kwargs={},
            response_metadata={'model_provider': 'anthropic'},
            id='lc_run--efa05280-6c77-4a8e-a0c9-a5c7e6390fbe'
        ),
        {
            'langgraph_step': 1,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:772693e6-6007-0269-aa0f-19acfcdd7244',
            'checkpoint_ns': 'model:772693e6-6007-0269-aa0f-19acfcdd7244',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    mode = 'messages'




    chunk =
    (
        AIMessageChunk(
            content=[{'text': ' can I help you today?', 'type': 'text', 'index': 0}],
            additional_kwargs={},
            response_metadata={'model_provider': 'anthropic'},
            id='lc_run--efa05280-6c77-4a8e-a0c9-a5c7e6390fbe'
        ),
        {
            'langgraph_step': 1,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:772693e6-6007-0269-aa0f-19acfcdd7244',
            'checkpoint_ns': 'model:772693e6-6007-0269-aa0f-19acfcdd7244',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    mode = 'messages'




    chunk =
    (
        AIMessageChunk(
            content=[],
            additional_kwargs={},
            response_metadata={'stop_reason': 'end_turn', 'stop_sequence': None, 'model_provider': 'anthropic'},
            id='lc_run--efa05280-6c77-4a8e-a0c9-a5c7e6390fbe',
            usage_metadata={
                'input_tokens': 552,
                'output_tokens': 12,
                'total_tokens': 564,
                'input_token_details': {'cache_creation': 0, 'cache_read': 0}
            },
            chunk_position='last'
        ),
        {
            'langgraph_step': 1,
            'langgraph_node': 'model',
            'langgraph_triggers': ('branch:to:model',),
            'langgraph_path': ('__pregel_pull', 'model'),
            'langgraph_checkpoint_ns': 'model:772693e6-6007-0269-aa0f-19acfcdd7244',
            'checkpoint_ns': 'model:772693e6-6007-0269-aa0f-19acfcdd7244',
            'ls_provider': 'anthropic',
            'ls_model_name': 'claude-sonnet-4-5-20250929',
            'ls_model_type': 'chat',
            'ls_temperature': None,
            'ls_max_tokens': 64000
        }
    )




    mode = 'updates'




    chunk =
    {
        'model': {
            'messages': [
                AIMessage(
                    content=[{'text': 'Hello! How can I help you today?', 'type': 'text', 'index': 0}],
                    additional_kwargs={},
                    response_metadata={
                        'model_name': 'claude-sonnet-4-5-20250929',
                        'model_provider': 'anthropic',
                        'stop_reason': 'end_turn',
                        'stop_sequence': None
                    },
                    id='lc_run--efa05280-6c77-4a8e-a0c9-a5c7e6390fbe',
                    usage_metadata={
                        'input_tokens': 552,
                        'output_tokens': 12,
                        'total_tokens': 564,
                        'input_token_details': {'cache_creation': 0, 'cache_read': 0}
                    }
                )
            ]
        }
    }


