Table of Contents
- Why Haiku 4.5 Changes the Game for Tool Use
- Fundamentals: What Tool Use Actually Is
- Prompt Design for Reliable Function Calling
- Output Validation and Error Handling
- Cost Optimisation Strategies
- Common Failure Modes and How to Fix Them
- Real-World Implementation Patterns
- Scaling Tool Use Across Your Platform
- Integration with Your Existing Stack
- 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:
- Schema comprehension: Understanding JSON schemas, parameter constraints (required/optional, type validation, enum constraints), and nested object structures
- Parameter binding: Mapping user intent to the correct parameters without hallucinating fields that don’t exist
- Error recovery: When given feedback that a function call failed, it learns from the error message and adjusts its next attempt
- 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:
- Tool definition: You define available tools with JSON schemas, descriptions, and parameter constraints
- User request: User provides input (text, data, context)
- Model inference: Haiku 4.5 processes the request and decides whether to call a tool
- Tool call generation: Model outputs structured JSON with function name and arguments
- Parsing and validation: Your code parses the JSON and validates arguments against the schema
- Function execution: You invoke the actual function (API call, database query, webhook, etc.)
- Result handling: You capture the result (success, error, exception) and feed it back to the model
- 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:
- Query users with specific filters
- Check each user for orders
- Update the filtered set
- 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:
- Parse the JSON (it should always be valid, but network errors happen)
- Check the tool name exists in your tool registry
- Validate the input against the tool’s schema
- 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:
- Retry with feedback: Feed the error message back to Haiku 4.5 and ask it to fix the call
- Fallback: Use a default tool or ask the user for clarification
- 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:
- Make tool descriptions more specific. Instead of “Query the database,” say “Query the customer database for customer details by ID, email, or name.”
- Separate tools by domain. If you have 10 database tools, group them:
query_customer_db,query_order_db,query_product_db. This reduces confusion. - 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:
- 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."
}
- Use enums for constrained values. If a parameter has only a few valid values, list them.
- 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:
- 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.
- 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."
}
- 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:
- 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
}
- 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.”
- 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:
- 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'?"
- 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:
- Customer submits: “I can’t log in to my account. My email changed.”
- Haiku 4.5 calls
get_account_detailswith customer_id - Result shows email is outdated
- Haiku 4.5 asks customer for new email
- Customer provides new email
- Haiku 4.5 calls
update_account_settingto update email - 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:
- Calls
list_datasetsto see what data is available - Calls
query_datasetwith a SQL query to get top products by revenue - Calls
schedule_pipelineto create a weekly report - 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
-
Haiku 4.5 excels at tool use: 94% first-attempt accuracy, sub-second latency, $0.80/$4 per 1M tokens.
-
Prompt design matters: Clear system prompts, specific tool descriptions, and parameter constraints unlock Haiku 4.5’s full potential.
-
Validation is essential: Validate tool calls at the JSON level, handle tool execution errors gracefully, and implement retry logic with circuit breakers.
-
Cost optimisation is real: Prompt caching, tool selection, and batch processing can reduce costs by 60–75% vs. larger models.
-
Failure modes are predictable: Hallucinated tools, incorrect parameters, sequencing errors, and infinite retries all have specific fixes.
-
Real-world patterns work: Customer support, data orchestration, and compliance automation are proven use cases.
-
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:
- Start with a single workflow (e.g., customer support)
- Define 3–5 tools with clear descriptions and constraints
- Implement validation and error handling
- Test with real users and iterate on prompts
- Monitor tool call accuracy, latency, and cost
- 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.