A developer should implement a Claude client tool as a narrow, application-controlled transaction. Define a precise name, description, and input JSON Schema; let Claude request the operation; then make application code validate the call, resolve the authenticated actor and target, enforce policy, obtain any required approval, execute through an allowlisted handler, and return a bounded result or explicit error. Record enough evidence to explain every consequential attempt, and fail closed when identity, authorization, approval, input, or execution state is uncertain.
The safe procedure is: expose only the tools appropriate to the current task, inspect every returned tool_use block, validate before dispatch, authorize independently of the model, gate side effects, execute with idempotency and least privilege, send a matching tool_result, and continue only while the loop remains within its call, time, and cost limits. Claude can select a tool and propose arguments; it does not execute client tools or grant permission to use them. A valid schema is an interface contract, not an authorization decision.
Understand Where Claude Tools Execute
Anthropic's current tool-use overview divides tools primarily by execution location.
- Client tools run in infrastructure controlled by the application. They include tools the developer defines and client-executed tools whose schemas Anthropic defines. Claude emits a tool_use block; application code decides whether and how to execute it and returns a tool_result.
- Server tools run on Anthropic's infrastructure. Their results are incorporated through the documented server-tool flow rather than a custom application handler.
This distinction changes who owns execution, but it does not erase governance. An application must still decide which tools to expose, what data to send, which authenticated users may request an operation, and whether a server-side capability is acceptable for the workload. Review each current server tool's documentation because types, availability, billing, and behavior can change.
A direct Claude tool definition is also not an MCP server. It is a tool interface supplied to a Claude request. A Model Context Protocol (MCP) server is a protocol endpoint that can expose tools and other capabilities to compatible hosts and clients. Building that protocol boundary, choosing transports, and deciding among tools, Skills, plugins, and MCP belongs in MCP Server Development and Choosing Between Tools, Skills, and MCP.
Define Focused Tools That Claude Can Select Correctly
The current tool-definition contract uses a tool name, a detailed plaintext description, and an input_schema expressed as JSON Schema. The definition should help Claude answer three questions: what the tool does, when it should or should not be used, and what each parameter means.
Name the capability, not its implementation
Choose a stable, descriptive name that maps to one reviewed handler. Namespacing can reduce ambiguity when tools span services. Avoid leaking internal class names, dynamically accepting arbitrary handler names, or making a generic execute_action tool that can reach unrelated systems.
Focus does not require one tool for every endpoint. Related operations can be consolidated when an explicit action field makes their shared purpose clearer and reduces selection ambiguity. Split a tool when operations have different permissions, approval rules, failure semantics, or owners. The security boundary should be understandable from the definition and the dispatch policy.
Write descriptions as selection guidance
A strong description states:
- the capability and result;
- appropriate and inappropriate use cases;
- the meaning, format, and effect of each input;
- important limitations or prerequisites; and
- whether the operation reads data, proposes a change, or causes a side effect.
Descriptions guide model selection; they do not enforce policy. Never put credentials in a description, and never rely on wording such as “administrators only” to block execution. The handler must prove that condition from trusted application state.
Make the input schema narrow
Use JSON Schema to express types, required fields, enumerations, formats, nested objects, and other supported constraints. Prefer semantic identifiers over free-form command text, and reject unknown fields when the supported schema and validator permit it. For example, a proposed notification tool can constrain the channel and require an approved template identifier without accepting arbitrary executable content:
{
"name": "notifications_send",
"description": "Send one reviewed notification template to an authorized recipient. Use only after the application has resolved the recipient and approval policy. This tool does not create templates or bypass communication preferences.",
"input_schema": {
"type": "object",
"properties": {
"recipient_id": { "type": "string", "minLength": 1 },
"template_id": { "type": "string", "minLength": 1 },
"channel": { "type": "string", "enum": ["email", "sms"] }
},
"required": ["recipient_id", "template_id", "channel"],
"additionalProperties": false
}
}
This is an illustrative application contract, not a vendor-provided notification tool. Even if a generated call conforms to the schema, the application must still verify that the recipient exists, the actor may contact that recipient, the template is approved, consent and policy permit the chosen channel, and the operation has not already succeeded.
Where supported, strict tool use can improve conformance to a compatible schema. Recheck the current supported subset and model behavior before relying on it. Strict conformance still proves only that the generated arguments match the declared shape; it does not prove that values are truthful, resources are in scope, or execution is authorized.
Implement the Client Tool-Use Loop
The documented client tool-use loop is a request-response round trip. The application sends available tools with the conversation. Claude may return one or more tool_use blocks. The application executes approved client operations, appends the complete assistant response to history, and sends matching tool_result blocks in the next user message. Claude then uses those results to continue.
An application-controlled loop can follow this pattern:
while within_turn_budget:
response = call_claude(messages, tools=allowed_tools)
append_complete_assistant_response(messages, response)
calls = collect_client_tool_use_blocks(response)
if calls is empty:
return verified_final_response(response)
results = []
for call in calls:
handler = allowlisted_registry.lookup(call.name)
if handler is missing:
results.append(error_result(call.id, "unknown_tool"))
continue
arguments = validate_schema_and_semantics(call.input, handler.contract)
actor, target = resolve_trusted_execution_context()
authorize(actor, handler.operation, target, arguments)
require_bound_approval_if_needed(actor, target, arguments)
operation_key = reserve_idempotent_operation(actor, target, arguments)
outcome = execute_with_limits(handler, arguments, operation_key)
audit_attempt_and_outcome(call, actor, target, outcome)
results.append(to_bounded_tool_result(call.id, outcome))
append_tool_results_as_one_user_message(messages, results)
raise ControlledStop("tool loop budget exhausted")
This pseudocode describes application responsibilities rather than a drop-in SDK implementation. In a real handler, errors from validation, authorization, approval, or execution should be converted into safe, structured outcomes without exposing secrets or internal stack traces. The application must also preserve the message ordering and result format required by the current API.
Validate, Authorize, and Approve Before Dispatch
Treat the model-produced tool name and arguments as untrusted input. A secure dispatcher performs distinct checks in a deliberate order.
Validate structure and meaning
Validate the input object against the registered schema, then apply application semantics the schema cannot prove. Resolve identifiers through trusted data access, normalize values according to the domain contract, check resource state, and reject stale or contradictory inputs. Do not construct shell commands, SQL, file paths, URLs, or handler names by concatenating model-produced strings.
Authorize from trusted identity and policy
Authorization must use authenticated application identity, server-side policy, resource ownership, tenant boundaries, and current permission state. Never accept an actor, role, tenant, or authorization flag merely because Claude supplied it as a tool argument. Limit each handler's credentials, network reach, filesystem access, and downstream permissions to the smallest capability it needs.
Bind approval to the exact consequence
Require explicit approval for consequential or difficult-to-reverse actions such as sending communications, making purchases, changing access, deleting data, deploying code, or operating external systems. Present the human with the resolved action, target, material parameters, expected effect, and relevant cost or risk.
An approval should be scoped and time-bounded. Bind it to the authenticated actor, action, target, normalized arguments, and operation version; expire it after a reasonable interval; and revalidate authorization and resource state immediately before execution. A vague approval for “continue” must not authorize a materially different call generated later.
Make Execution Idempotent and Auditable
Retries, network timeouts, and repeated model turns can duplicate side effects. For a mutating operation, define an application-level idempotency key or operation record before execution. The key should represent the approved business action, not assume that a tool_use identifier will remain stable across a regenerated request.
On a retry, the handler should return the recorded outcome or safely resume the operation rather than repeat it blindly. If the downstream system cannot support idempotency, expose that limitation, narrow automatic retry behavior, and require reconciliation or human review after an uncertain result.
Keep an audit record appropriate to the risk. Useful fields include:
- authenticated actor and tenant;
- tool name and registered definition version;
- normalized target and non-secret argument digest;
- policy and approval decision identifiers;
- idempotency or operation key;
- start time, completion state, and bounded result category; and
- correlation identifiers for the Claude request and downstream system.
Audit logs must not become a secret store. Redact credentials, personal data, raw document content, and sensitive tool results unless retention is explicitly justified and protected.
Return Results and Errors Safely
Anthropic's current tool-call handling guidance requires each client tool_result to reference its corresponding tool_use_id. Tool results immediately follow the assistant tool-use turn in message history, and result blocks precede any additional text in the user content array. If one assistant response contains multiple client calls, return the required results together rather than creating an interleaved conversation.
Return only the information Claude needs for the next decision. Prefer stable identifiers, explicit status, and high-signal fields over large raw payloads. Tool results can contain third-party or user-controlled content, so keep that material in the result boundary and treat it as untrusted data rather than new instructions.
Distinguish error classes
Use a stable application error taxonomy:
- Invalid call: unknown tool, schema failure, unsupported value, or failed semantic validation. Do not execute.
- Denied call: identity, authorization, policy, or approval is absent or no longer valid. Do not execute, and do not invite the model to bypass the control.
- Business conflict: the resource changed, a prerequisite is missing, or the requested state is already satisfied. Return a safe status and the permitted next action.
- Transient execution failure: a dependency timed out or temporarily failed. Retry only when the operation is idempotent and the retry policy permits it.
- Uncertain outcome: the downstream system may have committed the action but confirmation was lost. Reconcile by operation key before any retry.
- Permanent failure: the action cannot succeed under the current contract. Stop or request a revised user decision.
For a tool execution error, return an error result using the current API's documented is_error mechanism and a concise, non-sensitive explanation. Do not fabricate a successful result, silently drop a requested call, or expose exception traces and credentials. The tool-use troubleshooting guide is the current reference for malformed result ordering, missing result blocks, invented parameters, and other request-time failures.
Constrain Agentic Dispatch and Preserve User Control
An agent can repeat the tool loop and select among multiple capabilities, but autonomy does not widen authority. Build a registry that maps approved tool names to fixed handlers and policy classes. At each turn, expose only the subset relevant to the current workflow, actor, environment, and task state.
Apply explicit limits to:
- total tool calls, parallel calls, elapsed time, and service cost;
- retries and repeated failures;
- data volume entering or leaving each tool;
- resource scope and cross-tenant access;
- recursion, delegation, and chained side effects; and
- operations allowed before renewed human approval.
Keep the user informed before consequential actions and report the actual result afterward. If the requested goal changes, approval expires, policy state changes, or a result introduces a new consequential action, stop and obtain a new decision. The model may recommend a next step, but application policy owns whether that step is offered, approved, and executed.
Fail Safely and Diagnose the Right Layer
Safe failure preserves truth and control. When a call cannot proceed, the system should state what category failed, what did not execute, whether the outcome is known, and which permitted recovery path exists. Stop the loop when repeated calls do not make progress, the same error recurs, the call budget is exhausted, or execution state becomes ambiguous.
Diagnose failures by layer:
- revise the tool name, description, or visible tool set when Claude selects the wrong capability;
- revise the schema or examples when generated arguments are structurally wrong;
- correct application validation or dispatch when a valid call reaches the wrong handler;
- correct identity, policy, or approval logic when an unauthorized call can execute;
- correct handler and dependency behavior when execution fails after authorization; and
- correct result construction or message history when Claude cannot consume a completed outcome.
Do not weaken validation or authorization merely to improve tool-call success rates. Use Structured Claude Outputs, Validation, and Defensive Parsing for the broader distinction between structural and semantic validation, and Securing Claude Applications with Guardrails, Hooks, and Secret Management for application-wide identity, secrets, sandboxing, and incident controls.
Common Tool Implementation Mistakes
- Treating a valid schema as permission. Validate shape, then authorize the resolved operation independently.
- Giving Claude a generic executor. Register focused handlers and never dispatch arbitrary code or method names from model text.
- Using descriptions as security policy. Descriptions guide selection; application controls enforce access.
- Returning unbounded tool output. Send the smallest safe result needed for the next step and retain untrusted-data boundaries.
- Retrying a mutation after an unknown outcome. Reconcile by an application operation key before executing again.
- Approving an intent rather than an action. Bind approval to exact normalized parameters and recheck state before execution.
- Interleaving tool results incorrectly. Preserve the current Messages API content-block ordering and match every result to its call.
- Logging secrets for observability. Record decisions and identifiers without copying protected values into logs.
- Confusing a tool with an MCP server. Direct tool use defines a callable interface; MCP adds a protocol and deployment boundary covered separately.
Relevance to Claude Certified Developer – Foundations
The Claude Certified Developer – Foundations Exam Guide includes tool descriptions and schemas, client-versus-server tools, tool loops, error handling, agentic dispatch, approvals, and user control within its public developer scope.
The durable skill is preserving the separation of responsibilities: Claude requests a capability, the schema describes acceptable input shape, the application proves authority and executes client tools, and the result returns through the documented conversation contract. Reliability and safety depend on all four layers remaining visible and independently testable.
Conclusion
Safe Claude tool implementation begins with a focused definition and ends with an auditable result. Between those points, application code must validate meaning, resolve trusted identity, enforce authorization, bind approvals, dispatch through an allowlist, execute idempotently, and return a bounded result or explicit error.
Keep schema conformance separate from permission, keep client execution outside the model, and stop safely when outcome or authority is uncertain. This procedure preserves user control while giving Claude enough structured capability to complete useful multi-step work.
Authoritative Sources
- Tool use with Claude
- How tool use works
- Define tools
- Handle tool calls
- Troubleshoot tool use
- Claude Certified Developer – Foundations Exam Guide
Related Reading
- Securing Claude Applications with Guardrails, Hooks, and Secret Management
- Claude Agent and Workflow Architecture Decision Framework
- Claude Messages API and SDK Integration Foundations
- Structured Claude Outputs, Validation, and Defensive Parsing
- MCP Server Development and Choosing Between Tools, Skills, and MCP

