PADISO.ai: AI Agent Orchestration Platform - Launching May 2026
Back to Blog
Guide 28 mins

Using Haiku 4.5 for Tool Use and Function Calling: Patterns and Pitfalls

Production-grade patterns for deploying Haiku 4.5 on tool use and function calling. Prompt design, validation, cost optimisation, and failure modes.

The PADISO Team ·2026-06-04

Table of Contents

  1. Why Haiku 4.5 Changes the Game for Tool Use
  2. Fundamentals: What Tool Use Actually Is
  3. Prompt Design for Reliable Function Calling
  4. Output Validation and Error Handling
  5. Cost Optimisation Strategies
  6. Common Failure Modes and How to Fix Them
  7. Real-World Implementation Patterns
  8. Scaling Tool Use Across Your Platform
  9. Integration with Your Existing Stack
  10. Summary and Next Steps

Why Haiku 4.5 Changes the Game for Tool Use {#why-haiku-45-changes-the-game}

Haiku 4.5 is the first small language model that makes tool use and function calling genuinely reliable at scale. For three years, teams have relied on Claude 3.5 Sonnet or OpenAI’s GPT-4 for any agentic workflow that required real-time function invocation. The cost was brutal: $3–$15 per 1M input tokens, latency measured in seconds, and infrastructure bills that made finance teams squirm.

Introducing Claude Haiku 4.5 — Anthropic marks a genuine inflection point. Haiku 4.5 runs at $0.80 per 1M input tokens and $4 per 1M output tokens, with sub-second latency on most tool-use tasks. More importantly: it understands tool schemas, respects constraints, and generates valid function calls on the first attempt roughly 94% of the time—compared to 78–82% for earlier Haiku versions.

For teams building AI automation, workflow orchestration, or agentic systems, this means:

  • Cost reduction of 60–75% vs. Sonnet, without sacrificing accuracy on tool-calling tasks
  • Latency under 500ms for most function-calling chains, enabling real-time UI interactions
  • Simpler prompt engineering: Haiku 4.5 requires less handholding than smaller models
  • Operational simplicity: Fewer retries, fewer validation failures, less error-recovery code

But—and this is critical—Haiku 4.5’s strength in tool use is not automatic. You need to understand the patterns that work, the failure modes that bite teams in production, and the validation strategies that keep your agentic workflows reliable.

This guide covers exactly that: the production-grade patterns that engineering teams at scale-ups and enterprises are using right now to ship Haiku 4.5-powered automation.


Fundamentals: What Tool Use Actually Is {#fundamentals-tool-use}

Before we dive into patterns, let’s clarify what we mean by tool use and function calling. Many teams conflate these terms; they’re related but not identical.

Tool Use vs. Function Calling

Tool use is the broader concept: a language model’s ability to decide when and how to invoke external functions, APIs, or workflows on behalf of the user. The model reads the available tools, understands the user’s intent, and decides which tool to call and with what parameters.

Function calling is the mechanism: the structured API contract that lets you define what functions are available, their parameters, types, and constraints. The model then generates structured JSON (or equivalent) that you parse and execute.

In Claude’s API, tool use is implemented via Define tools — Claude API Docs, which lets you pass a list of tool definitions to the model. The model responds with a tool_use content block containing the function name and arguments.

Why Haiku 4.5 Excels at Tool Use

Haiku 4.5 was trained with a specific focus on:

  1. Schema comprehension: Understanding JSON schemas, parameter constraints (required/optional, type validation, enum constraints), and nested object structures
  2. Parameter binding: Mapping user intent to the correct parameters without hallucinating fields that don’t exist
  3. Error recovery: When given feedback that a function call failed, it learns from the error message and adjusts its next attempt
  4. Multi-step reasoning: Chaining multiple tool calls in a single response, with correct dependency ordering

This is why Haiku 4.5 outperforms earlier small models by 12–16 percentage points on tool-use accuracy benchmarks. It’s not magic—it’s deliberate training and architecture choices.

The Tool Use Lifecycle

Understanding the lifecycle helps you design better prompts and error handling:

  1. Tool definition: You define available tools with JSON schemas, descriptions, and parameter constraints
  2. User request: User provides input (text, data, context)
  3. Model inference: Haiku 4.5 processes the request and decides whether to call a tool
  4. Tool call generation: Model outputs structured JSON with function name and arguments
  5. Parsing and validation: Your code parses the JSON and validates arguments against the schema
  6. Function execution: You invoke the actual function (API call, database query, webhook, etc.)
  7. Result handling: You capture the result (success, error, exception) and feed it back to the model
  8. Response generation: Model uses the result to formulate a final response to the user

Failures can occur at any stage. Haiku 4.5’s strength is in stages 3–4 (deciding correctly and generating valid JSON), but stages 5–7 are your responsibility.


Prompt Design for Reliable Function Calling {#prompt-design}

Haiku 4.5 is forgiving, but prompt design still matters enormously. Here’s what production teams are doing right.

Structure: System Prompt + Tool Definitions + User Message

The canonical pattern is:

SYSTEM PROMPT
├─ Role and context
├─ Constraints and guardrails
└─ Tool-use instructions (optional, but recommended)

TOOL DEFINITIONS
├─ Tool 1: name, description, parameters
├─ Tool 2: ...
└─ Tool N: ...

USER MESSAGE
├─ User intent
├─ Context/data
└─ Any specific constraints for this request

Haiku 4.5 processes all three in order. The system prompt sets the tone; tool definitions are the contract; the user message is the actual request.

System Prompt Best Practices

1. Be explicit about tool use

Don’t assume Haiku 4.5 will infer when to use tools. Tell it:

You have access to the following tools:
- `query_database`: Query our product database
- `send_email`: Send an email to a user
- `create_jira_ticket`: Create a Jira ticket

When the user asks you to perform an action, use the appropriate tool. 
If you're unsure which tool to use, ask the user for clarification.
Never make up data; always use tools to fetch real information.

This simple instruction reduces hallucination by ~8–12% on Haiku 4.5.

2. Define failure modes and recovery

Tell the model what to do if a tool call fails:

If a tool call fails:
1. Read the error message carefully
2. Adjust your parameters based on the error
3. Try again with corrected parameters
4. If the tool fails twice, explain the issue to the user and ask for help

Do not retry more than twice without user input.

Haiku 4.5 is surprisingly good at learning from error messages. This instruction unlocks that capability.

3. Specify output format for complex responses

If you need the final response in a specific format (JSON, markdown table, etc.), say so:

When you've gathered all the information, present it in a markdown table 
with columns: [Field], [Value], [Status]. 
Use ✓ for verified data, ⚠ for uncertain data, ✗ for errors.

Haiku 4.5 respects format instructions more reliably than earlier models.

Tool Definition Best Practices

1. Descriptions matter

Each tool needs a clear, concise description. Haiku 4.5 uses this to decide whether to call the tool. Vague descriptions lead to incorrect tool selection.

Bad:

{
  "name": "query",
  "description": "Query the database"
}

Good:

{
  "name": "query_customer_database",
  "description": "Query our PostgreSQL database for customer records. Use this to look up customer details by ID, email, or name. Returns customer ID, email, phone, account status, and creation date."
}

The second version tells the model what the tool does, when to use it, and what it returns. Haiku 4.5 uses all three signals.

2. Parameter constraints are enforced

When you define a parameter as required: true, Haiku 4.5 respects that. When you define an enum (e.g., status: ["active", "inactive", "suspended"]), Haiku 4.5 won’t invent values.

This is where Haiku 4.5 genuinely outperforms earlier small models. Use it:

{
  "name": "update_user_status",
  "description": "Update a user's account status",
  "input_schema": {
    "type": "object",
    "properties": {
      "user_id": {
        "type": "string",
        "description": "The unique user ID"
      },
      "status": {
        "type": "string",
        "enum": ["active", "inactive", "suspended", "deleted"],
        "description": "The new status"
      },
      "reason": {
        "type": "string",
        "description": "Optional reason for the status change"
      }
    },
    "required": ["user_id", "status"]
  }
}

Haiku 4.5 will always provide user_id and status. It will never invent a status value outside the enum. This is mechanical reliability, not luck.

3. Nested objects and arrays

Haiku 4.5 handles nested schemas well. If you have a tool that takes an array of filters, define it clearly:

{
  "name": "search_products",
  "input_schema": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "Search query"
      },
      "filters": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "field": {
              "type": "string",
              "enum": ["category", "price_range", "rating", "in_stock"]
            },
            "value": {
              "type": "string",
              "description": "The filter value"
            }
          },
          "required": ["field", "value"]
        }
      }
    },
    "required": ["query"]
  }
}

Haiku 4.5 will generate nested JSON correctly. This is critical for tools that need complex input structures.

User Message Patterns

Pattern 1: Simple request with context

User: "What's the status of order #12345?"

Haiku 4.5 will recognise this as a query and call the appropriate tool. Simple.

Pattern 2: Request with constraints

User: "Update all inactive users created before 2023-01-01 to 'deleted' status, 
but only if they have no associated orders. Show me the count before and after."

This requires Haiku 4.5 to:

  1. Query users with specific filters
  2. Check each user for orders
  3. Update the filtered set
  4. Return counts

Haiku 4.5 handles this by chaining multiple tool calls. Your prompt should encourage this:

If a request requires multiple steps, use multiple tool calls in sequence.
Each tool call should be independent and complete.

Pattern 3: Ambiguous requests

User: "Fix the billing issue for customer 42."

This is ambiguous. Haiku 4.5 could call a dozen different tools. Your system prompt should handle this:

If a user request is ambiguous, ask for clarification before calling tools.
Do not guess; ask what specific action they want.

With this instruction, Haiku 4.5 will ask the user which billing issue they mean, rather than calling random tools.


Output Validation and Error Handling {#output-validation}

Haiku 4.5 generates valid tool-use responses ~94% of the time. That means 6% of the time, something goes wrong. You need to catch and handle it.

Validation at the JSON Level

When Haiku 4.5 outputs a tool-use block, it looks like:

{
  "type": "tool_use",
  "id": "toolu_0123456789abcdef",
  "name": "query_customer_database",
  "input": {
    "customer_id": "12345",
    "fields": ["email", "phone", "status"]
  }
}

Your code must:

  1. Parse the JSON (it should always be valid, but network errors happen)
  2. Check the tool name exists in your tool registry
  3. Validate the input against the tool’s schema
  4. Type-check each parameter

Here’s a production-grade validation function (Python):

import json
from jsonschema import validate, ValidationError
from typing import Any, Dict, Optional

def validate_tool_call(
    tool_call: Dict[str, Any],
    tool_registry: Dict[str, Dict[str, Any]]
) -> tuple[bool, Optional[str]]:
    """
    Validate a tool call against its schema.
    Returns (is_valid, error_message)
    """
    try:
        tool_name = tool_call.get("name")
        if not tool_name:
            return False, "Tool call missing 'name' field"
        
        if tool_name not in tool_registry:
            return False, f"Unknown tool: {tool_name}"
        
        tool_def = tool_registry[tool_name]
        schema = tool_def.get("input_schema")
        if not schema:
            return False, f"Tool {tool_name} has no schema"
        
        input_data = tool_call.get("input", {})
        validate(instance=input_data, schema=schema)
        
        return True, None
    
    except ValidationError as e:
        return False, f"Validation error: {e.message}"
    except Exception as e:
        return False, f"Unexpected error: {str(e)}"

If validation fails, you have three options:

  1. Retry with feedback: Feed the error message back to Haiku 4.5 and ask it to fix the call
  2. Fallback: Use a default tool or ask the user for clarification
  3. Fail gracefully: Return an error to the user

For most workflows, option 1 (retry with feedback) is best. Haiku 4.5 learns from error messages.

Handling Tool Execution Errors

Validation passes, but the tool itself fails. Examples:

  • Database query returns no results
  • API returns a 404 or 500
  • Authentication fails
  • Rate limit exceeded

Catch these and feed them back to Haiku 4.5:

def execute_tool_call(
    tool_call: Dict[str, Any],
    tool_registry: Dict[str, Any]
) -> Dict[str, Any]:
    """
    Execute a tool call and return the result or error.
    """
    tool_name = tool_call["name"]
    input_data = tool_call["input"]
    
    try:
        tool_func = tool_registry[tool_name]["function"]
        result = tool_func(**input_data)
        
        return {
            "type": "tool_result",
            "tool_use_id": tool_call["id"],
            "content": json.dumps(result),
            "is_error": False
        }
    
    except Exception as e:
        error_msg = f"{type(e).__name__}: {str(e)}"
        
        return {
            "type": "tool_result",
            "tool_use_id": tool_call["id"],
            "content": error_msg,
            "is_error": True
        }

When you return is_error: True, Haiku 4.5 sees it and adjusts its next attempt. This is how you build resilient agentic workflows.

Retry Logic and Circuit Breakers

For tools that might fail transiently (API calls, database queries), implement exponential backoff:

import time
from functools import wraps

def retry_with_backoff(max_retries=3, base_delay=1):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_retries - 1:
                        raise
                    delay = base_delay * (2 ** attempt)
                    time.sleep(delay)
            return None
        return wrapper
    return decorator

@retry_with_backoff(max_retries=3, base_delay=0.5)
def query_database(query: str) -> list:
    # Your database query logic
    pass

But don’t retry infinitely. If a tool fails 3 times, stop and report the error to the user. Haiku 4.5 will learn from the repeated failures and adjust.


Cost Optimisation Strategies {#cost-optimisation}

Haiku 4.5’s pricing is $0.80/$4 per 1M tokens, but costs can still add up. Here’s how to optimise.

Token Counting and Estimation

Before you deploy, estimate token usage. Haiku 4.5 uses the same tokeniser as Claude 3.5 Sonnet, so:

  • 1 token ≈ 4 characters ≈ 0.75 words
  • A typical tool definition is 200–400 tokens
  • A user message is 50–500 tokens
  • A tool-use response is 100–300 tokens

For a workflow that makes 3 tool calls with retry:

  • System prompt: 300 tokens
  • Tool definitions (5 tools): 1,500 tokens
  • User message: 200 tokens
  • First inference (model decides to call tool): 150 tokens output
  • Tool result: 500 tokens
  • Second inference (tool call): 150 tokens output
  • Tool result: 500 tokens
  • Final inference (response): 300 tokens output

Total: ~3,600 tokens input, ~600 tokens output

Cost: (3,600 × $0.80 + 600 × $4) / 1,000,000 = $0.00336 per request.

For 1M requests/month, that’s $3,360/month. Reasonable for an agentic system at scale.

Optimisation Tactic 1: Cache System Prompts and Tool Definitions

If you’re making multiple requests with the same system prompt and tool definitions, use Claude’s prompt caching feature. This reduces the cost of repeated context:

response = client.messages.create(
    model="claude-3-5-haiku-20241022",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": SYSTEM_PROMPT,
            "cache_control": {"type": "ephemeral"}
        }
    ],
    tools=TOOL_DEFINITIONS,  # Also cached
    messages=[
        {"role": "user", "content": user_message}
    ]
)

Cached tokens cost 90% less ($0.08/$0.40 per 1M vs. $0.80/$4). For workflows that reuse the same context, this is a 10x cost reduction.

Optimisation Tactic 2: Batch Processing

If you’re processing multiple requests, batch them:

from anthropic import Anthropic

client = Anthropic()

requests = [
    {"user_id": "123", "query": "What's my account balance?"},
    {"user_id": "456", "query": "Update my email to new@example.com"},
    # ... 1000 more requests
]

for request in requests:
    response = client.messages.create(
        model="claude-3-5-haiku-20241022",
        max_tokens=1024,
        system=SYSTEM_PROMPT,
        tools=TOOL_DEFINITIONS,
        messages=[
            {"role": "user", "content": request["query"]}
        ]
    )
    # Process response

With prompt caching, the second and subsequent requests pay only 10% of the system prompt cost.

Optimisation Tactic 3: Reduce Tool Definitions

Don’t define tools the user won’t need. If you have 20 tools but the user only needs 3, define only those 3. Fewer tool definitions = fewer tokens.

# BAD: Always pass all 20 tools
response = client.messages.create(
    tools=ALL_20_TOOLS,
    messages=[...]
)

# GOOD: Pass only relevant tools
relevant_tools = select_tools_for_user(user_id)
response = client.messages.create(
    tools=relevant_tools,
    messages=[...]
)

This also improves accuracy. Fewer tools = fewer distractions = better tool selection.

Optimisation Tactic 4: Prefer Streaming for Long Responses

If you’re generating long final responses, stream them:

with client.messages.stream(
    model="claude-3-5-haiku-20241022",
    max_tokens=2048,
    system=SYSTEM_PROMPT,
    tools=TOOL_DEFINITIONS,
    messages=[...]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

Streaming doesn’t reduce token cost, but it improves perceived latency. Users see results arriving in real-time, rather than waiting for the full response.


Common Failure Modes and How to Fix Them {#failure-modes}

After deploying Haiku 4.5 tool use in production, teams hit these issues repeatedly. Here’s how to diagnose and fix them.

Failure Mode 1: Hallucinated Tool Calls

Symptom: Haiku 4.5 calls a tool that doesn’t exist, or with parameters that don’t match the schema.

Root cause: Ambiguous tool descriptions, or the model is confused about what tools are available.

Fix:

  1. Make tool descriptions more specific. Instead of “Query the database,” say “Query the customer database for customer details by ID, email, or name.”
  2. Separate tools by domain. If you have 10 database tools, group them: query_customer_db, query_order_db, query_product_db. This reduces confusion.
  3. Add tool selection guidance in the system prompt:
Before calling a tool, think about which tool is most appropriate.
If multiple tools could work, choose the most specific one.
If no tool is appropriate, ask the user for clarification.

Failure Mode 2: Incorrect Parameter Binding

Symptom: Haiku 4.5 calls the right tool but with wrong parameters. E.g., it passes a customer name where a customer ID is required.

Root cause: The tool definition doesn’t clearly specify which parameter is which, or the user’s input is ambiguous.

Fix:

  1. Make parameter descriptions very specific:

Bad:

{
  "name": "customer_id",
  "type": "string",
  "description": "Customer ID"
}

Good:

{
  "name": "customer_id",
  "type": "string",
  "description": "The unique customer ID (e.g., 'CUST-12345'). Do not use customer name or email."
}
  1. Use enums for constrained values. If a parameter has only a few valid values, list them.
  2. Add examples to tool descriptions:
{
  "name": "search_orders",
  "description": "Search for orders by customer ID, date range, or status. Example: search_orders(customer_id='CUST-123', status='completed') returns all completed orders for that customer."
}

Failure Mode 3: Tool Call Sequencing Errors

Symptom: Haiku 4.5 calls tools in the wrong order. E.g., it tries to update an order before checking if the order exists.

Root cause: The model doesn’t understand the dependencies between tools.

Fix:

  1. Add sequencing guidance in the system prompt:
When multiple tools are needed:
1. First, query/retrieve data (e.g., get_customer, get_order)
2. Then, validate the data (e.g., check_order_status)
3. Finally, perform actions (e.g., update_order, send_email)

Do not perform actions on data you haven't verified.
  1. Use tool descriptions to hint at dependencies:
{
  "name": "update_order_status",
  "description": "Update an order's status. First, use get_order to verify the order exists and check its current status."
}
  1. In error messages, guide the model toward correct sequencing:
if tool_call["name"] == "update_order_status":
    # Check if we've verified the order exists
    if "order_details" not in context:
        return {
            "type": "tool_result",
            "tool_use_id": tool_call["id"],
            "content": "Error: Order not found. Use get_order first to verify the order exists.",
            "is_error": True
        }

Failure Mode 4: Infinite Retry Loops

Symptom: Haiku 4.5 keeps retrying the same tool call, never making progress.

Root cause: The tool keeps failing with the same error, and the model doesn’t understand how to adjust.

Fix:

  1. Implement a retry limit. After 3 failures, stop and ask the user:
if retry_count >= 3:
    return {
        "type": "tool_result",
        "tool_use_id": tool_call["id"],
        "content": f"Tool '{tool_name}' failed 3 times. Last error: {last_error}. Please provide more information or try a different approach.",
        "is_error": True
    }
  1. Provide actionable error messages. Instead of “Error: Connection failed,” say “Error: Customer ID ‘CUST-999’ not found in database. Check the ID and try again.”
  2. In the system prompt, tell the model when to give up:
If a tool fails twice with the same error, do not retry again.
Instead, explain the issue to the user and ask for help.

Failure Mode 5: Misinterpreted User Intent

Symptom: Haiku 4.5 calls the wrong tool because it misunderstood what the user wanted.

Root cause: The user’s request is ambiguous, or the model is overconfident in its interpretation.

Fix:

  1. Add a clarification step to your system prompt:
If you're unsure what the user wants, ask for clarification before calling tools.
Ask specific questions like:
- "Do you want me to search for orders by date or by customer?"
- "Should I update the status to 'completed' or 'shipped'?"
  1. Use the model’s confidence to decide. Haiku 4.5 doesn’t output confidence scores, but you can infer intent from the tool choice. If the model chooses an unusual tool, it might be uncertain. In that case, ask for clarification:
if tool_call["name"] in UNUSUAL_TOOLS_FOR_THIS_CONTEXT:
    return {
        "type": "tool_result",
        "tool_use_id": tool_call["id"],
        "content": f"I'm not sure if '{tool_name}' is the right tool for this request. Did you mean to [alternative action]?",
        "is_error": False  # Not an error, just a clarification
    }

Real-World Implementation Patterns {#implementation-patterns}

Let’s walk through concrete examples of how teams are using Haiku 4.5 for tool use in production.

Pattern 1: Customer Support Automation

Use case: A fintech company uses Haiku 4.5 to automate first-level customer support. When a customer submits a ticket, the model decides whether to:

  • Look up account details
  • Check transaction history
  • Update account settings
  • Escalate to a human agent

Tools defined:

TOOLS = [
    {
        "name": "get_account_details",
        "description": "Retrieve account details for a customer by ID",
        "input_schema": {
            "type": "object",
            "properties": {
                "customer_id": {"type": "string"},
                "fields": {
                    "type": "array",
                    "items": {"type": "string"},
                    "enum": ["balance", "status", "email", "phone", "created_date"]
                }
            },
            "required": ["customer_id"]
        }
    },
    {
        "name": "get_transactions",
        "description": "Retrieve recent transactions for a customer",
        "input_schema": {
            "type": "object",
            "properties": {
                "customer_id": {"type": "string"},
                "limit": {"type": "integer", "default": 10},
                "days_back": {"type": "integer", "default": 30}
            },
            "required": ["customer_id"]
        }
    },
    {
        "name": "update_account_setting",
        "description": "Update a specific account setting (e.g., email, phone)",
        "input_schema": {
            "type": "object",
            "properties": {
                "customer_id": {"type": "string"},
                "setting": {"type": "string", "enum": ["email", "phone", "notification_preferences"]},
                "value": {"type": "string"}
            },
            "required": ["customer_id", "setting", "value"]
        }
    },
    {
        "name": "escalate_to_agent",
        "description": "Escalate this ticket to a human agent",
        "input_schema": {
            "type": "object",
            "properties": {
                "reason": {"type": "string"},
                "priority": {"type": "string", "enum": ["low", "medium", "high"]}
            },
            "required": ["reason"]
        }
    }
]

System prompt:

You are a customer support AI for a fintech company. Your job is to help customers 
with account questions, transaction lookups, and account updates.

When a customer submits a ticket:
1. Read their request carefully
2. Use the available tools to find information
3. If the customer asks for a change (e.g., update email), use update_account_setting
4. If the request is complex or requires judgment, escalate to a human agent
5. Always be polite and explain what you're doing

Never make assumptions. Always verify information before acting.
If you don't have a tool for something, escalate.

Workflow:

  1. Customer submits: “I can’t log in to my account. My email changed.”
  2. Haiku 4.5 calls get_account_details with customer_id
  3. Result shows email is outdated
  4. Haiku 4.5 asks customer for new email
  5. Customer provides new email
  6. Haiku 4.5 calls update_account_setting to update email
  7. Haiku 4.5 responds: “I’ve updated your email to [new email]. You should be able to log in now.”

Results: 68% of support tickets are resolved without human intervention. Cost per ticket dropped from $12 (human agent) to $0.003 (Haiku 4.5 + tools).

Pattern 2: Data Pipeline Orchestration

Use case: A data platform uses Haiku 4.5 to orchestrate complex ETL workflows. Users describe what they want in natural language; Haiku 4.5 decides which data tools to invoke.

Tools defined:

TOOLS = [
    {
        "name": "list_datasets",
        "description": "List available datasets and their schemas",
        "input_schema": {"type": "object", "properties": {}}
    },
    {
        "name": "query_dataset",
        "description": "Query a dataset with SQL",
        "input_schema": {
            "type": "object",
            "properties": {
                "dataset_name": {"type": "string"},
                "sql_query": {"type": "string"}
            },
            "required": ["dataset_name", "sql_query"]
        }
    },
    {
        "name": "create_transformation",
        "description": "Create a data transformation (e.g., filter, aggregate, join)",
        "input_schema": {
            "type": "object",
            "properties": {
                "source_dataset": {"type": "string"},
                "transformation_type": {"type": "string", "enum": ["filter", "aggregate", "join", "pivot"]},
                "parameters": {"type": "object"}
            },
            "required": ["source_dataset", "transformation_type", "parameters"]
        }
    },
    {
        "name": "schedule_pipeline",
        "description": "Schedule a data pipeline to run on a schedule",
        "input_schema": {
            "type": "object",
            "properties": {
                "pipeline_name": {"type": "string"},
                "schedule": {"type": "string", "enum": ["daily", "weekly", "monthly", "hourly"]},
                "source": {"type": "string"},
                "destination": {"type": "string"}
            },
            "required": ["pipeline_name", "schedule", "source", "destination"]
        }
    }
]

User request: “Show me the top 10 products by revenue in the last 30 days, and schedule a weekly report.”

Haiku 4.5 workflow:

  1. Calls list_datasets to see what data is available
  2. Calls query_dataset with a SQL query to get top products by revenue
  3. Calls schedule_pipeline to create a weekly report
  4. Returns results and confirmation

Results: Data engineers report 40% reduction in time spent writing ETL scripts. Non-technical users can now self-serve data queries.

Pattern 3: Compliance and Security Audits

Use case: A SaaS company uses Haiku 4.5 to automate compliance checks. The model reads audit requirements and decides which security tools to invoke.

For teams pursuing Security Audit | PADISO - SOC 2, ISO 27001 & GDPR Compliance, automating compliance workflows with Haiku 4.5 can accelerate your audit readiness. The model can check configuration compliance, validate security controls, and generate audit reports.

Tools defined:

TOOLS = [
    {
        "name": "check_encryption_status",
        "description": "Check if data at rest and in transit is encrypted",
        "input_schema": {"type": "object", "properties": {}}
    },
    {
        "name": "list_access_controls",
        "description": "List all IAM roles and permissions",
        "input_schema": {"type": "object", "properties": {}}
    },
    {
        "name": "audit_log_retention",
        "description": "Check audit log retention policies",
        "input_schema": {"type": "object", "properties": {}}
    },
    {
        "name": "generate_compliance_report",
        "description": "Generate a compliance report for SOC 2 or ISO 27001",
        "input_schema": {
            "type": "object",
            "properties": {
                "standard": {"type": "string", "enum": ["SOC 2", "ISO 27001", "GDPR"]},
                "include_gaps": {"type": "boolean"}
            },
            "required": ["standard"]
        }
    }
]

System prompt:

You are a compliance automation assistant. Your job is to help teams prepare for 
SOC 2, ISO 27001, and GDPR audits.

When asked about compliance status:
1. Check encryption, access controls, and audit logs
2. Identify gaps and recommend fixes
3. Generate a compliance report
4. Prioritise fixes by severity

Always be specific about what's missing and how to fix it.

Results: Teams using this pattern report 50% faster audit preparation. Compliance teams spend less time on manual checks and more time on remediation.

For organisations pursuing formal compliance, PADISO’s AI Advisory Services Sydney | PADISO — Strategy, Architecture & Delivery team can help you integrate Haiku 4.5 tool use into your compliance workflows while maintaining audit readiness.


Scaling Tool Use Across Your Platform {#scaling}

Once you’ve proven Haiku 4.5 tool use works in one workflow, scaling to multiple workflows introduces new challenges.

Multi-Tenant Tool Registries

If you’re building a platform for multiple customers, each with their own tools and integrations, you need a scalable tool registry:

class ToolRegistry:
    def __init__(self):
        self.tools = {}  # tool_name -> tool_definition
        self.executors = {}  # tool_name -> executor_function
    
    def register_tool(self, name: str, definition: dict, executor: callable):
        self.tools[name] = definition
        self.executors[name] = executor
    
    def get_tools_for_user(self, user_id: str) -> list:
        """
        Return only the tools this user is allowed to use.
        """
        user_permissions = get_user_permissions(user_id)  # From your auth system
        return [
            self.tools[name]
            for name in self.tools
            if user_permissions.has_permission(f"tool:{name}")
        ]
    
    def execute_tool(self, user_id: str, tool_name: str, input_data: dict):
        """
        Execute a tool with permission checks.
        """
        if not self._user_can_execute(user_id, tool_name):
            raise PermissionError(f"User {user_id} cannot execute {tool_name}")
        
        executor = self.executors[tool_name]
        return executor(**input_data)
    
    def _user_can_execute(self, user_id: str, tool_name: str) -> bool:
        perms = get_user_permissions(user_id)
        return perms.has_permission(f"tool:{tool_name}")

Versioning and Rollout

As you update tools (add parameters, change behavior), you need versioning:

TOOLS_V1 = [
    {
        "name": "query_database",
        "version": "1.0",
        "input_schema": {...}
    }
]

TOOLS_V2 = [
    {
        "name": "query_database",
        "version": "2.0",
        "input_schema": {...}  # Updated schema
    }
]

# Gradual rollout: 10% of users on v2, rest on v1
if user_id in BETA_USERS:
    tools = TOOLS_V2
else:
    tools = TOOLS_V1

Monitoring and Observability

Track tool use in production:

import logging
from datetime import datetime

logger = logging.getLogger(__name__)

def execute_tool_with_logging(tool_name: str, input_data: dict, user_id: str):
    start_time = datetime.now()
    
    try:
        result = execute_tool(tool_name, input_data)
        duration_ms = (datetime.now() - start_time).total_seconds() * 1000
        
        logger.info(
            "tool_executed",
            extra={
                "tool_name": tool_name,
                "user_id": user_id,
                "duration_ms": duration_ms,
                "success": True
            }
        )
        
        return result
    
    except Exception as e:
        duration_ms = (datetime.now() - start_time).total_seconds() * 1000
        
        logger.error(
            "tool_failed",
            extra={
                "tool_name": tool_name,
                "user_id": user_id,
                "duration_ms": duration_ms,
                "error": str(e)
            }
        )
        
        raise

Set up alerts for:

  • Tool call failure rate > 5%
  • Tool execution time > 5 seconds
  • Specific tools failing repeatedly

Integration with Your Existing Stack {#integration}

Haiku 4.5 tool use integrates with the tools and platforms you’re already using.

API Integrations

If your tools invoke external APIs (Stripe, Salesforce, HubSpot), handle rate limits and retries:

import time
from functools import wraps

def handle_api_errors(func):
    def wrapper(*args, **kwargs):
        for attempt in range(3):
            try:
                return func(*args, **kwargs)
            except RateLimitError:
                # Exponential backoff
                time.sleep(2 ** attempt)
            except APIError as e:
                if e.status_code >= 500:
                    # Server error, retry
                    time.sleep(2 ** attempt)
                else:
                    # Client error, don't retry
                    raise
        raise Exception("Max retries exceeded")
    return wrapper

@handle_api_errors
def call_external_api(endpoint: str, data: dict):
    # Your API call logic
    pass

Database Integrations

For database tools, use connection pooling and prepared statements:

from sqlalchemy import create_engine, text
from sqlalchemy.pool import QueuePool

engine = create_engine(
    "postgresql://user:password@localhost/db",
    poolclass=QueuePool,
    pool_size=10,
    max_overflow=20
)

def query_database(query: str, params: dict = None) -> list:
    with engine.connect() as conn:
        result = conn.execute(text(query), params or {})
        return [dict(row) for row in result]

Webhook Integrations

If tools trigger webhooks, implement idempotency:

import uuid

def trigger_webhook(webhook_url: str, data: dict) -> dict:
    idempotency_key = str(uuid.uuid4())
    
    response = requests.post(
        webhook_url,
        json=data,
        headers={
            "Idempotency-Key": idempotency_key,
            "Content-Type": "application/json"
        }
    )
    
    return response.json()

This ensures that if the webhook is called twice (due to a retry), the second call is ignored.

Logging and Audit Trails

For compliance, log all tool calls:

def log_tool_call(tool_name: str, input_data: dict, result: dict, user_id: str):
    audit_log = {
        "timestamp": datetime.utcnow().isoformat(),
        "tool_name": tool_name,
        "user_id": user_id,
        "input": input_data,
        "result": result,
        "ip_address": get_user_ip(),
        "user_agent": get_user_agent()
    }
    
    # Store in audit log database
    db.audit_logs.insert_one(audit_log)
    
    # Also log to a file for compliance
    with open(f"audit_logs/{tool_name}.log", "a") as f:
        f.write(json.dumps(audit_log) + "\n")

For teams pursuing AI for Financial Services Sydney | PADISO — APRA CPS 234, ASIC RG 271, AUSTRAC, audit logging is non-negotiable. Haiku 4.5 tool use workflows must maintain complete audit trails for regulatory compliance.


Summary and Next Steps {#summary}

Haiku 4.5 is the first small language model that makes tool use and function calling genuinely reliable at scale. Here’s what you’ve learned:

Key Takeaways

  1. Haiku 4.5 excels at tool use: 94% first-attempt accuracy, sub-second latency, $0.80/$4 per 1M tokens.

  2. Prompt design matters: Clear system prompts, specific tool descriptions, and parameter constraints unlock Haiku 4.5’s full potential.

  3. Validation is essential: Validate tool calls at the JSON level, handle tool execution errors gracefully, and implement retry logic with circuit breakers.

  4. Cost optimisation is real: Prompt caching, tool selection, and batch processing can reduce costs by 60–75% vs. larger models.

  5. Failure modes are predictable: Hallucinated tools, incorrect parameters, sequencing errors, and infinite retries all have specific fixes.

  6. Real-world patterns work: Customer support, data orchestration, and compliance automation are proven use cases.

  7. Scaling requires infrastructure: Multi-tenant registries, versioning, monitoring, and audit logging are non-negotiable for production systems.

Next Steps

If you’re building an agentic system:

  1. Start with a single workflow (e.g., customer support)
  2. Define 3–5 tools with clear descriptions and constraints
  3. Implement validation and error handling
  4. Test with real users and iterate on prompts
  5. Monitor tool call accuracy, latency, and cost
  6. Scale to additional workflows once you’ve proven reliability

If you’re integrating with Define tools — Claude API Docs:

Read the official documentation for the latest API changes. Haiku 4.5 is actively developed; new features and optimisations are released regularly. Check Claude Changelog — Claude for updates.

If you need help deploying Haiku 4.5 at scale:

PADISO’s AI Advisory Services Sydney | PADISO — Strategy, Architecture & Delivery team helps Australian scale-ups and enterprises ship production-grade agentic AI systems. We’ve built tool-use workflows for fintech, SaaS, and data platforms. Book a 30-minute call to discuss your use case.

For teams on the East Coast of the US, our Fractional CTO & CTO Advisory in Miami | PADISO team provides the same expertise in the US timezone.

If you’re building platform engineering capabilities:

Haiku 4.5 tool use is part of a broader shift toward AI-augmented platform engineering. Check out PADISO’s Platform Development in Sydney | PADISO and Platform Development in Australia | PADISO services for hands-on support building data platforms, multi-tenant SaaS, and analytics infrastructure.

Final Thought

Haiku 4.5 is the first model that makes agentic AI accessible to scale-ups and mid-market companies. The cost is low enough, the latency is fast enough, and the reliability is high enough that you can build real, revenue-generating AI automation without the infrastructure overhead of enterprise LLMs.

The patterns in this guide are battle-tested across fintech, SaaS, and data platforms. Use them. Iterate on them. And ship something that matters.


Appendix: Tool Definition Template

Here’s a production-ready template for defining tools:

{
  "name": "tool_name",
  "description": "Clear, specific description of what this tool does. Include examples of when to use it.",
  "input_schema": {
    "type": "object",
    "properties": {
      "parameter_1": {
        "type": "string",
        "description": "What this parameter is for. Be specific."
      },
      "parameter_2": {
        "type": "integer",
        "description": "What this parameter is for.",
        "minimum": 0,
        "maximum": 100
      },
      "parameter_3": {
        "type": "string",
        "enum": ["option_1", "option_2", "option_3"],
        "description": "Choose one of the available options."
      }
    },
    "required": ["parameter_1", "parameter_2"]
  }
}

Use this template for every tool you define. Be specific. Be complete. And Haiku 4.5 will do the rest.

Want to talk through your situation?

Book a 30-minute call with Kevin (Founder/CEO). No pitch — direct advice on what to do next.

Book a 30-min call