Generative AI  

Building a Date Assistant Using Anthropic Claude, Python, and Function Calling

In today’s world of AI-powered applications, large language models (LLMs) like Claude by Anthropic offer a human-like understanding of natural language. But when it comes to precise tasks, like date calculations, calendar parsing, or time-based reasoning, relying on natural language alone can lead to inconsistent results. That’s where function calling comes in.

In this article, we’ll walk through a powerful example of how to integrate Anthropic Claude with Python function calling to build a smart date assistant. The assistant understands natural language queries and uses tools (functions) to return precise, structured answers involving date extraction, date arithmetic, and real-time data computation.

Anthropic Claude

What We'll Build?

A smart assistant that can:

  • Answer: “What’s today’s date?”
  • Extract: “Let’s meet next week” → 2025-07-14
  • Calculate: “How many days until Christmas?”
  • Stream responses in real-time
  • Call Python functions to get accurate results

Technologies Used

  • Anthropic SDK: Send/receive messages to Claude
  • Python: Define and execute tools (functions)
  • Streaming API: Display Claude’s response in real time
  • .env config: Securely load API key

Implementation

1. Setup and Configuration

Install dependencies: pip install anthropic python-dotenv

Create a .env file and add your Claude API key: ANTHROPIC_API_KEY=your-api-key-here

Imports

import anthropic
import os
from dotenv import load_dotenv
from datetime import datetime, timedelta
import time

We load environment variables to securely access the Anthropic API key:

load_dotenv()
ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY")
client = anthropic.Anthropic(api_key=ANTHROPIC_API_KEY)

2. Define Functions (Tools)

These Python functions will act as external tools that Claude can call when needed.

a. Extract Natural Dates

def extract_date_from_text(text_input):
    today = datetime.now()
    if "tomorrow" in text_input.lower():
        return (today + timedelta(days=1)).strftime("%Y-%m-%d")
    elif "next week" in text_input.lower():
        return (today + timedelta(days=7)).strftime("%Y-%m-%d")
    elif "next month" in text_input.lower():
        next_month = today.replace(day=1) + timedelta(days=32)
        return next_month.replace(day=1).strftime("%Y-%m-%d")
    elif "next friday" in text_input.lower():
        days_ahead = 4 - today.weekday()  # Friday is 4
        if days_ahead <= 0:
            days_ahead += 7
        return (today + timedelta(days=days_ahead)).strftime("%Y-%m-%d")
    else:
        return None

b. Get Today’s Date

def get_current_date():
    return datetime.now().strftime("%Y-%m-%d")

c. Days Until a Target Date

def calculate_days_until(target_date):
    try:
        target = datetime.strptime(target_date, "%Y-%m-%d")
        today = datetime.now()
        return (target - today).days
    except:
        return None

3. Tool Definitions for Claude

These are JSON schemas that Claude uses to understand what each tool does and what inputs it needs.

function_definitions = [
    {
        "name": "extract_date_from_text",
        "description": "Extract and parse date from natural language text input",
        "input_schema": {
            "type": "object",
            "properties": {
                "text_input": {
                    "type": "string",
                    "description": "The natural language text containing a date reference"
                }
            },
            "required": ["text_input"]
        }
    },
    ...
]

4. Function Dispatcher

We map each tool name to its actual Python function:

available_functions = {
    "extract_date_from_text": extract_date_from_text,
    "get_current_date": get_current_date,
    "calculate_days_until": calculate_days_until
}

5. Claude Interaction with Tool Use + Streaming

Here’s where everything comes together. Full Function:

def process_streaming_with_functions(user_input, max_retries=3):
    messages = [{"role": "user", "content": f"Help me with this date-related query: {user_input}"}]

    for attempt in range(max_retries):
        try:
            response = client.messages.create(
                model="claude-3-5-sonnet-20241022",
                max_tokens=1000,
                temperature=0.2,
                system="You are a helpful assistant that can extract dates and perform date calculations. Use the available functions when needed to provide accurate results.",
                messages=messages,
                tools=function_definitions
            )

            # Handle function calls
            function_calls = []
            for content in response.content:
                if content.type == "tool_use":
                    function_calls.append(content)

            if function_calls:
                messages.append({"role": "assistant", "content": response.content})

                # Execute each tool
                tool_results = []
                for call in function_calls:
                    function_name = call.name
                    function_args = call.input
                    result = available_functions[function_name](**function_args)
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": call.id,
                        "content": str(result)
                    })

                # Append results and stream final reply
                messages.append({"role": "user", "content": tool_results})
                final_response = ""
                with client.messages.stream(
                    model="claude-3-5-sonnet-20241022",
                    max_tokens=1000,
                    temperature=0.2,
                    system="You are a helpful assistant.",
                    messages=messages
                ) as stream:
                    for event in stream:
                        if event.type == "content_block_delta" and event.delta.type == "text_delta":
                            print(event.delta.text, end="", flush=True)
                            final_response += event.delta.text
                print("\n")
                return final_response
            else:
                return "".join(c.text for c in response.content if c.type == "text")

        except anthropic.RateLimitError:
            time.sleep(2 ** attempt)
        except anthropic.APIError as e:
            time.sleep(1)
        except Exception as e:
            return f"ERROR: {e}"

6. Testing

We run multiple prompts to evaluate how Claude uses tools:

def run_function_call_tests():
    test_queries = [
        "What's today's date?",
        "I need to schedule something for tomorrow",
        "How many days until 2025-12-25?",
        "Extract the date from: 'Let's meet next week'",
        "What date is next Friday?",
        "When is next month starting?"
    ]
    for query in test_queries:
        result = process_streaming_with_functions(query)
        print(f"\nFinal result: {result}")

Sample Output

Test 2/6
Processing: 'I need to schedule something for tomorrow'
Claude's response:
Sure! Let's determine what date "tomorrow" refers to.

Function call: extract_date_from_text
Input: {'text_input': 'I need to schedule something for tomorrow'}

extract_date_from_text returned: 2025-07-09

Final response:
You should schedule it for 2025-07-09.

Conclusion

This smart assistant blends LLM intelligence with programmatic logic, producing highly accurate, user-friendly, and scalable results. If you're building agents, chatbots, or automation tools, this is a powerful pattern you’ll want in your toolbox. 

Combining Claude’s intelligence with Python’s precision unlocks real, production-grade assistants. We have now learned how to:

  • Call tools/functions from Claude
  • Stream final answers
  • Handle retries and errors
  • Test multi-step conversations

This Smart Date Assistant is a foundation for any LLM-based app that needs structured logic with natural language input.